Add task completion notification trigger
When a task is completed, send push notifications to all residence users (except the person who completed it). Uses the existing NotificationService.CreateAndSendNotification method. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -74,6 +74,9 @@ func SetupRouter(deps *Dependencies) *gin.Engine {
|
|||||||
contractorService := services.NewContractorService(contractorRepo, residenceRepo)
|
contractorService := services.NewContractorService(contractorRepo, residenceRepo)
|
||||||
documentService := services.NewDocumentService(documentRepo, residenceRepo)
|
documentService := services.NewDocumentService(documentRepo, residenceRepo)
|
||||||
notificationService := services.NewNotificationService(notificationRepo, gorushClient)
|
notificationService := services.NewNotificationService(notificationRepo, gorushClient)
|
||||||
|
|
||||||
|
// Wire up notification service to task service (for task completion notifications)
|
||||||
|
taskService.SetNotificationService(notificationService)
|
||||||
subscriptionService := services.NewSubscriptionService(subscriptionRepo, residenceRepo, taskRepo, contractorRepo, documentRepo)
|
subscriptionService := services.NewSubscriptionService(subscriptionRepo, residenceRepo, taskRepo, contractorRepo, documentRepo)
|
||||||
|
|
||||||
// Initialize middleware
|
// Initialize middleware
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
package services
|
package services
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
|
|
||||||
"github.com/treytartt/mycrib-api/internal/dto/requests"
|
"github.com/treytartt/mycrib-api/internal/dto/requests"
|
||||||
@@ -23,8 +26,9 @@ var (
|
|||||||
|
|
||||||
// TaskService handles task business logic
|
// TaskService handles task business logic
|
||||||
type TaskService struct {
|
type TaskService struct {
|
||||||
taskRepo *repositories.TaskRepository
|
taskRepo *repositories.TaskRepository
|
||||||
residenceRepo *repositories.ResidenceRepository
|
residenceRepo *repositories.ResidenceRepository
|
||||||
|
notificationService *NotificationService
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTaskService creates a new task service
|
// NewTaskService creates a new task service
|
||||||
@@ -35,6 +39,11 @@ func NewTaskService(taskRepo *repositories.TaskRepository, residenceRepo *reposi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetNotificationService sets the notification service (for breaking circular dependency)
|
||||||
|
func (s *TaskService) SetNotificationService(ns *NotificationService) {
|
||||||
|
s.notificationService = ns
|
||||||
|
}
|
||||||
|
|
||||||
// === Task CRUD ===
|
// === Task CRUD ===
|
||||||
|
|
||||||
// GetTask gets a task by ID with access check
|
// GetTask gets a task by ID with access check
|
||||||
@@ -461,16 +470,69 @@ func (s *TaskService) CreateCompletion(req *requests.CreateTaskCompletionRequest
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reload
|
// Reload completion with user info
|
||||||
completion, err = s.taskRepo.FindCompletionByID(completion.ID)
|
completion, err = s.taskRepo.FindCompletionByID(completion.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send notification to residence owner and other users
|
||||||
|
s.sendTaskCompletedNotification(task, completion)
|
||||||
|
|
||||||
resp := responses.NewTaskCompletionResponse(completion)
|
resp := responses.NewTaskCompletionResponse(completion)
|
||||||
return &resp, nil
|
return &resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sendTaskCompletedNotification sends notifications when a task is completed
|
||||||
|
func (s *TaskService) sendTaskCompletedNotification(task *models.Task, completion *models.TaskCompletion) {
|
||||||
|
if s.notificationService == nil {
|
||||||
|
log.Debug().Msg("Notification service not configured, skipping task completion notification")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get all users with access to this residence
|
||||||
|
users, err := s.residenceRepo.GetResidenceUsers(task.ResidenceID)
|
||||||
|
if err != nil {
|
||||||
|
log.Error().Err(err).Uint("task_id", task.ID).Msg("Failed to get residence users for notification")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
completedByName := "Someone"
|
||||||
|
if completion.CompletedBy.ID > 0 {
|
||||||
|
completedByName = completion.CompletedBy.GetFullName()
|
||||||
|
}
|
||||||
|
|
||||||
|
title := "Task Completed"
|
||||||
|
body := fmt.Sprintf("%s completed: %s", completedByName, task.Title)
|
||||||
|
|
||||||
|
data := map[string]interface{}{
|
||||||
|
"task_id": task.ID,
|
||||||
|
"residence_id": task.ResidenceID,
|
||||||
|
"completion_id": completion.ID,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify all users except the one who completed the task
|
||||||
|
for _, user := range users {
|
||||||
|
if user.ID == completion.CompletedByID {
|
||||||
|
continue // Don't notify the person who completed it
|
||||||
|
}
|
||||||
|
|
||||||
|
go func(userID uint) {
|
||||||
|
ctx := context.Background()
|
||||||
|
if err := s.notificationService.CreateAndSendNotification(
|
||||||
|
ctx,
|
||||||
|
userID,
|
||||||
|
models.NotificationTaskCompleted,
|
||||||
|
title,
|
||||||
|
body,
|
||||||
|
data,
|
||||||
|
); err != nil {
|
||||||
|
log.Error().Err(err).Uint("user_id", userID).Uint("task_id", task.ID).Msg("Failed to send task completion notification")
|
||||||
|
}
|
||||||
|
}(user.ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// GetCompletion gets a task completion by ID
|
// GetCompletion gets a task completion by ID
|
||||||
func (s *TaskService) GetCompletion(completionID, userID uint) (*responses.TaskCompletionResponse, error) {
|
func (s *TaskService) GetCompletion(completionID, userID uint) (*responses.TaskCompletionResponse, error) {
|
||||||
completion, err := s.taskRepo.FindCompletionByID(completionID)
|
completion, err := s.taskRepo.FindCompletionByID(completionID)
|
||||||
|
|||||||
Reference in New Issue
Block a user