dukcapil/internal/processor/letter_disposition_processor.go
2025-09-08 12:24:37 +07:00

241 lines
8.3 KiB
Go

package processor
import (
"context"
"eslogad-be/internal/contract"
"eslogad-be/internal/entities"
"eslogad-be/internal/repository"
"eslogad-be/internal/transformer"
"github.com/google/uuid"
)
type LetterDispositionProcessor interface {
CreateDispositions(ctx context.Context, req *contract.CreateLetterDispositionRequest) (*contract.ListDispositionsResponse, error)
GetByLetterID(ctx context.Context, letterID uuid.UUID) ([]entities.LetterIncomingDisposition, error)
GetEnhancedDispositionsByLetter(ctx context.Context, letterID uuid.UUID) (*contract.ListEnhancedDispositionsResponse, error)
}
type LetterDispositionProcessorImpl struct {
dispositionRepo *repository.LetterIncomingDispositionRepository
dispositionDeptRepo *repository.LetterIncomingDispositionDepartmentRepository
dispositionActionSelRepo *repository.LetterDispositionActionSelectionRepository
dispositionNoteRepo *repository.DispositionNoteRepository
discussionRepo *repository.LetterDiscussionRepository
dispActionRepo *repository.DispositionActionRepository
activity *ActivityLogProcessorImpl
}
func NewLetterDispositionProcessor(
dispositionRepo *repository.LetterIncomingDispositionRepository,
dispositionDeptRepo *repository.LetterIncomingDispositionDepartmentRepository,
dispositionActionSelRepo *repository.LetterDispositionActionSelectionRepository,
dispositionNoteRepo *repository.DispositionNoteRepository,
discussionRepo *repository.LetterDiscussionRepository,
dispActionRepo *repository.DispositionActionRepository,
activity *ActivityLogProcessorImpl,
) *LetterDispositionProcessorImpl {
return &LetterDispositionProcessorImpl{
dispositionRepo: dispositionRepo,
dispositionDeptRepo: dispositionDeptRepo,
dispositionActionSelRepo: dispositionActionSelRepo,
dispositionNoteRepo: dispositionNoteRepo,
discussionRepo: discussionRepo,
dispActionRepo: dispActionRepo,
activity: activity,
}
}
func (p *LetterDispositionProcessorImpl) CreateDispositions(ctx context.Context, req *contract.CreateLetterDispositionRequest) (*contract.ListDispositionsResponse, error) {
disposition := &entities.LetterIncomingDisposition{
LetterID: req.LetterID,
DepartmentID: &req.FromDepartment,
Notes: req.Notes,
CreatedBy: req.CreatedBy,
}
if err := p.dispositionRepo.Create(ctx, disposition); err != nil {
return nil, err
}
if err := p.createDispositionDepartments(ctx, disposition.ID, req.LetterID, req.ToDepartmentIDs); err != nil {
return nil, err
}
if len(req.SelectedActions) > 0 {
if err := p.createActionSelectionsFromRequest(ctx, disposition.ID, req.SelectedActions); err != nil {
return nil, err
}
}
if p.activity != nil {
p.activity.LogDispositionCreated(ctx, req.LetterID, req.CreatedBy, len(req.ToDepartmentIDs))
}
// Build response
dispositions := []entities.LetterIncomingDisposition{*disposition}
response := p.buildDispositionsResponse(dispositions)
return response, nil
}
func (p *LetterDispositionProcessorImpl) GetByLetterID(ctx context.Context, letterID uuid.UUID) ([]entities.LetterIncomingDisposition, error) {
return p.dispositionRepo.ListByLetter(ctx, letterID)
}
func (p *LetterDispositionProcessorImpl) GetEnhancedDispositionsByLetter(ctx context.Context, letterID uuid.UUID) (*contract.ListEnhancedDispositionsResponse, error) {
// Get dispositions
dispositions, err := p.dispositionRepo.ListByLetter(ctx, letterID)
if err != nil {
return nil, err
}
// Get discussions
discussions, err := p.discussionRepo.ListByLetter(ctx, letterID)
if err != nil {
return nil, err
}
// Build enhanced response
enhancedDispositions := make([]contract.EnhancedDispositionResponse, 0, len(dispositions))
for _, disp := range dispositions {
// Build disposition response using existing structure
var dept contract.DepartmentResponse
if disp.Department.ID != uuid.Nil {
dept = *transformer.DepartmentEntityToContract(&disp.Department)
}
// Build departments
departments := make([]contract.DispositionDepartmentResponse, 0, len(disp.Departments))
for _, d := range disp.Departments {
departments = append(departments, contract.DispositionDepartmentResponse{
ID: d.ID,
DepartmentID: d.DepartmentID,
Department: transformer.DepartmentEntityToContract(d.Department),
})
}
// Build actions
actions := make([]contract.DispositionActionSelectionResponse, 0, len(disp.ActionSelections))
for _, a := range disp.ActionSelections {
if a.Action != nil {
actions = append(actions, contract.DispositionActionSelectionResponse{
ID: a.ID,
ActionID: a.ActionID,
Action: &contract.DispositionActionResponse{
ID: a.Action.ID.String(),
Code: a.Action.Code,
Label: a.Action.Label,
Description: a.Action.Description,
RequiresNote: a.Action.RequiresNote,
},
})
}
}
// Build notes
notes := make([]contract.DispositionNoteResponse, 0, len(disp.DispositionNotes))
for _, n := range disp.DispositionNotes {
var userResp *contract.UserResponse
if n.User != nil {
userResp = transformer.EntityToContract(n.User)
}
notes = append(notes, contract.DispositionNoteResponse{
ID: n.ID,
Note: n.Note,
CreatedAt: n.CreatedAt,
User: userResp,
})
}
enhancedDispositions = append(enhancedDispositions, contract.EnhancedDispositionResponse{
ID: disp.ID,
LetterID: disp.LetterID,
DepartmentID: disp.DepartmentID,
Notes: disp.Notes,
ReadAt: disp.ReadAt,
CreatedBy: disp.CreatedBy,
CreatedAt: disp.CreatedAt,
UpdatedAt: disp.UpdatedAt,
Department: dept,
Departments: departments,
Actions: actions,
DispositionNotes: notes,
})
}
// Get general discussions
var generalDiscussions []contract.LetterDiscussionResponse
for _, disc := range discussions {
generalDiscussions = append(generalDiscussions, *transformer.DiscussionEntityToContract(&disc))
}
return &contract.ListEnhancedDispositionsResponse{
Dispositions: enhancedDispositions,
Discussions: generalDiscussions,
}, nil
}
// Helper methods
func (p *LetterDispositionProcessorImpl) createDispositionDepartments(ctx context.Context, dispositionID, letterID uuid.UUID, departmentIDs []uuid.UUID) error {
departments := make([]entities.LetterIncomingDispositionDepartment, 0, len(departmentIDs))
for _, deptID := range departmentIDs {
departments = append(departments, entities.LetterIncomingDispositionDepartment{
LetterIncomingDispositionID: dispositionID,
LetterIncomingID: letterID,
DepartmentID: deptID,
Status: entities.DispositionDepartmentStatusPending,
})
}
if len(departments) > 0 {
return p.dispositionDeptRepo.CreateBulk(ctx, departments)
}
return nil
}
func (p *LetterDispositionProcessorImpl) createActionSelectionsFromRequest(ctx context.Context, dispositionID uuid.UUID, selectedActions []contract.CreateDispositionActionSelection) error {
selections := make([]entities.LetterDispositionActionSelection, 0, len(selectedActions))
for _, action := range selectedActions {
selections = append(selections, entities.LetterDispositionActionSelection{
DispositionID: dispositionID,
ActionID: action.ActionID,
})
}
if len(selections) > 0 {
return p.dispositionActionSelRepo.CreateBulk(ctx, selections)
}
return nil
}
func (p *LetterDispositionProcessorImpl) buildDispositionsResponse(dispositions []entities.LetterIncomingDisposition) *contract.ListDispositionsResponse {
dispositionResponses := make([]contract.DispositionResponse, 0, len(dispositions))
for _, disp := range dispositions {
dispositionResponses = append(dispositionResponses, *p.buildDispositionResponse(&disp))
}
return &contract.ListDispositionsResponse{
Dispositions: dispositionResponses,
}
}
func (p *LetterDispositionProcessorImpl) buildDispositionResponse(disp *entities.LetterIncomingDisposition) *contract.DispositionResponse {
return &contract.DispositionResponse{
ID: disp.ID,
LetterID: disp.LetterID,
DepartmentID: disp.DepartmentID,
Notes: disp.Notes,
ReadAt: disp.ReadAt,
CreatedBy: disp.CreatedBy,
CreatedAt: disp.CreatedAt,
UpdatedAt: disp.UpdatedAt,
}
}