package service import ( "context" "github.com/Caknoooo/go-gin-clean-starter/database/entities" dtodomain "github.com/Caknoooo/go-gin-clean-starter/modules/assignment/dto" "github.com/Caknoooo/go-gin-clean-starter/modules/assignment/query" "github.com/Caknoooo/go-gin-clean-starter/modules/assignment/repository" pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto" "github.com/google/uuid" "gorm.io/gorm" ) type AssignmentService interface { Create(ctx context.Context, req dtodomain.AssignmentCreateRequest) (dtodomain.AssignmentResponse, error) GetById(ctx context.Context, id string) (dtodomain.AssignmentResponse, error) GetAll(ctx context.Context, filter query.AssignmentFilter) ([]dtodomain.AssignmentResponse, int64, error) Update(ctx context.Context, req dtodomain.AssignmentUpdateRequest, id string) (dtodomain.AssignmentResponse, error) Delete(ctx context.Context, id string) error } type assignmentService struct { db *gorm.DB assignmentRepo repository.AssignmentRepository assignmentUserRepo repository.AssignmentUserRepository } func toAssignmentResponse(e entities.TAssignmentEntity) dtodomain.AssignmentResponse { client := pkgdto.IdNameResponse{} if e.Client.ID != uuid.Nil { client = pkgdto.IdNameResponse{ ID: e.Client.ID.String(), Name: e.Client.Name, } } users := make([]dtodomain.AssignmentUserResponse, 0) for _, user := range e.AssignmentUsers { userResp := dtodomain.AssignmentUserResponse{ ID: user.ID.String(), TaskType: user.TaskType, User: pkgdto.IdNameResponse{ID: user.User.ID.String(), Name: user.User.Name}, Role: pkgdto.IdNameResponse{ID: user.Role.ID.String(), Name: user.Role.Name}, Client: pkgdto.IdNameResponse{ID: user.Client.ID.String(), Name: user.Client.Name}, } users = append(users, userResp) } return dtodomain.AssignmentResponse{ ID: e.ID.String(), DocumentType: e.DocumentType, DocumentID: e.DocumentID.String(), Client: client, AssignmentUsers: users, } } func (s *assignmentService) Create(ctx context.Context, req dtodomain.AssignmentCreateRequest) (dtodomain.AssignmentResponse, error) { tx := s.db.Begin() defer func() { if r := recover(); r != nil { tx.Rollback() } }() clientUUID, err := uuid.Parse(req.ClientID) if err != nil { tx.Rollback() return dtodomain.AssignmentResponse{}, err } documentUUID, err := uuid.Parse(req.DocumentID) if err != nil { tx.Rollback() return dtodomain.AssignmentResponse{}, err } assignment := entities.TAssignmentEntity{ DocumentType: req.DocumentType, DocumentID: documentUUID, ClientID: clientUUID, } created, err := s.assignmentRepo.Create(ctx, tx, assignment) if err != nil { tx.Rollback() return dtodomain.AssignmentResponse{}, err } // Bulk create assignment users var assignmentUsers []entities.TAssignmentUserEntity for _, userReq := range req.AssignmentUsers { userUUID, err := uuid.Parse(userReq.UserID) if err != nil { tx.Rollback() return dtodomain.AssignmentResponse{}, err } roleUUID, err := uuid.Parse(userReq.RoleID) if err != nil { tx.Rollback() return dtodomain.AssignmentResponse{}, err } clientUUID, err := uuid.Parse(userReq.ClientID) if err != nil { tx.Rollback() return dtodomain.AssignmentResponse{}, err } assignmentUsers = append(assignmentUsers, entities.TAssignmentUserEntity{ AssignmentID: created.ID, TaskType: userReq.TaskType, UserID: userUUID, RoleID: roleUUID, ClientID: clientUUID, }) } if len(assignmentUsers) > 0 { if err := s.assignmentUserRepo.BulkCreate(ctx, tx, assignmentUsers); err != nil { tx.Rollback() return dtodomain.AssignmentResponse{}, err } } tx.Commit() result, err := s.assignmentRepo.GetById(ctx, nil, created.ID.String()) if err != nil { return dtodomain.AssignmentResponse{}, err } return toAssignmentResponse(result), nil } func (s *assignmentService) GetById(ctx context.Context, id string) (dtodomain.AssignmentResponse, error) { assignment, err := s.assignmentRepo.GetById(ctx, nil, id) if err != nil { return dtodomain.AssignmentResponse{}, err } return toAssignmentResponse(assignment), nil } func (s *assignmentService) GetAll(ctx context.Context, filter query.AssignmentFilter) ([]dtodomain.AssignmentResponse, int64, error) { assignments, total, err := s.assignmentRepo.GetAll(ctx, filter) if err != nil { return nil, 0, err } var responses []dtodomain.AssignmentResponse for _, e := range assignments { responses = append(responses, toAssignmentResponse(e)) } if responses == nil { responses = make([]dtodomain.AssignmentResponse, 0) } return responses, total, nil } func (s *assignmentService) Update(ctx context.Context, req dtodomain.AssignmentUpdateRequest, id string) (dtodomain.AssignmentResponse, error) { tx := s.db.Begin() defer func() { if r := recover(); r != nil { tx.Rollback() } }() assignment, err := s.assignmentRepo.GetById(ctx, tx, id) if err != nil { tx.Rollback() return dtodomain.AssignmentResponse{}, err } if req.DocumentType != "" { assignment.DocumentType = req.DocumentType } if req.DocumentID != "" { docUUID, err := uuid.Parse(req.DocumentID) if err == nil { assignment.DocumentID = docUUID } } updated, err := s.assignmentRepo.Update(ctx, tx, assignment) if err != nil { tx.Rollback() return dtodomain.AssignmentResponse{}, err } tx.Commit() result, err := s.assignmentRepo.GetById(ctx, nil, updated.ID.String()) if err != nil { return dtodomain.AssignmentResponse{}, err } return toAssignmentResponse(result), nil } func (s *assignmentService) Delete(ctx context.Context, id string) error { tx := s.db.Begin() defer func() { if r := recover(); r != nil { tx.Rollback() } }() if err := s.assignmentRepo.Delete(ctx, tx, id); err != nil { tx.Rollback() return err } tx.Commit() return nil } func NewAssignmentService(db *gorm.DB, assignmentRepo repository.AssignmentRepository, assignmentUserRepo repository.AssignmentUserRepository) AssignmentService { return &assignmentService{ db: db, assignmentRepo: assignmentRepo, assignmentUserRepo: assignmentUserRepo, } }