181 lines
6.7 KiB
Go
181 lines
6.7 KiB
Go
package processor
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"eslogad-be/internal/contract"
|
|
"eslogad-be/internal/entities"
|
|
"eslogad-be/internal/repository"
|
|
"eslogad-be/internal/transformer"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type LetterDispositionDepartmentProcessor interface {
|
|
GetByLetterIncomingID(ctx context.Context, letterIncomingID uuid.UUID) ([]entities.LetterIncomingDispositionDepartment, error)
|
|
GetDepartmentDispositionStatus(ctx context.Context, letterIncomingID uuid.UUID) (*contract.ListDepartmentDispositionStatusResponse, error)
|
|
UpdateDispositionStatus(ctx context.Context, letterIncomingID uuid.UUID, departmentID uuid.UUID, userID uuid.UUID, req *contract.UpdateDispositionStatusRequest) (*contract.DepartmentDispositionStatusResponse, error)
|
|
CheckAndUpdateLetterCompletionStatus(ctx context.Context, letterIncomingID uuid.UUID) error
|
|
}
|
|
|
|
type LetterDispositionDepartmentProcessorImpl struct {
|
|
dispositionDeptRepo *repository.LetterIncomingDispositionDepartmentRepository
|
|
dispositionNoteRepo *repository.DispositionNoteRepository
|
|
letterRepo *repository.LetterIncomingRepository
|
|
}
|
|
|
|
func NewLetterDispositionDepartmentProcessor(
|
|
dispositionDeptRepo *repository.LetterIncomingDispositionDepartmentRepository,
|
|
dispositionNoteRepo *repository.DispositionNoteRepository,
|
|
letterRepo *repository.LetterIncomingRepository,
|
|
) *LetterDispositionDepartmentProcessorImpl {
|
|
return &LetterDispositionDepartmentProcessorImpl{
|
|
dispositionDeptRepo: dispositionDeptRepo,
|
|
dispositionNoteRepo: dispositionNoteRepo,
|
|
letterRepo: letterRepo,
|
|
}
|
|
}
|
|
|
|
// GetByLetterIncomingID retrieves all disposition departments for a letter
|
|
func (p *LetterDispositionDepartmentProcessorImpl) GetByLetterIncomingID(ctx context.Context, letterIncomingID uuid.UUID) ([]entities.LetterIncomingDispositionDepartment, error) {
|
|
return p.dispositionDeptRepo.GetByLetterIncomingID(ctx, letterIncomingID)
|
|
}
|
|
|
|
// GetDepartmentDispositionStatus retrieves disposition status for a specific letter
|
|
func (p *LetterDispositionDepartmentProcessorImpl) GetDepartmentDispositionStatus(ctx context.Context, letterIncomingID uuid.UUID) (*contract.ListDepartmentDispositionStatusResponse, error) {
|
|
dispositions, err := p.dispositionDeptRepo.GetByLetterIncomingID(ctx, letterIncomingID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
response := p.buildDispositionStatusResponse(dispositions)
|
|
return response, nil
|
|
}
|
|
|
|
func (p *LetterDispositionDepartmentProcessorImpl) UpdateDispositionStatus(ctx context.Context, letterIncomingID uuid.UUID, departmentID uuid.UUID, userID uuid.UUID, req *contract.UpdateDispositionStatusRequest) (*contract.DepartmentDispositionStatusResponse, error) {
|
|
dispDept, err := p.dispositionDeptRepo.GetByDispositionAndDepartment(ctx, letterIncomingID, departmentID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
now := time.Now()
|
|
var dispositionStatus entities.LetterIncomingDispositionDepartmentStatus
|
|
var readAt, completedAt *time.Time
|
|
|
|
switch req.Status {
|
|
case "completed":
|
|
dispositionStatus = entities.DispositionDepartmentStatusCompleted
|
|
completedAt = &now
|
|
readAt = &now // Mark as read when completing
|
|
case "read":
|
|
dispositionStatus = entities.DispositionDepartmentStatusRead
|
|
readAt = &now
|
|
case "dispositioned":
|
|
dispositionStatus = entities.DispositionDepartmentStatusDispositioned
|
|
default:
|
|
dispositionStatus = entities.DispositionDepartmentStatusPending
|
|
}
|
|
|
|
// Extract notes for the update
|
|
notes := ""
|
|
if req.Notes != nil && *req.Notes != "" {
|
|
notes = *req.Notes
|
|
}
|
|
|
|
if err := p.dispositionDeptRepo.UpdateStatus(ctx, dispDept.ID, dispositionStatus, notes, readAt, completedAt); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Check and update letter completion status
|
|
if err := p.CheckAndUpdateLetterCompletionStatus(ctx, letterIncomingID); err != nil {
|
|
// Log error but don't fail the status update
|
|
}
|
|
|
|
// Get updated record for response
|
|
updatedDispDept, err := p.dispositionDeptRepo.GetByID(ctx, dispDept.ID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return p.buildSingleDispositionStatusResponse(updatedDispDept), nil
|
|
}
|
|
|
|
// CheckAndUpdateLetterCompletionStatus checks if all dispositions are completed and updates letter status
|
|
func (p *LetterDispositionDepartmentProcessorImpl) CheckAndUpdateLetterCompletionStatus(ctx context.Context, letterIncomingID uuid.UUID) error {
|
|
// Get all disposition departments for this letter
|
|
dispositions, err := p.dispositionDeptRepo.GetByLetterIncomingID(ctx, letterIncomingID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// Check if all dispositions are completed
|
|
allCompleted := true
|
|
for _, disp := range dispositions {
|
|
if disp.Status == entities.DispositionDepartmentStatusPending {
|
|
allCompleted = false
|
|
break
|
|
}
|
|
}
|
|
|
|
// If all dispositions are completed, update the letter status to completed
|
|
if allCompleted && len(dispositions) > 0 {
|
|
letter, err := p.letterRepo.GetByID(ctx, letterIncomingID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
letter.Status = "completed"
|
|
if err := p.letterRepo.Update(ctx, letter); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Helper methods
|
|
|
|
func (p *LetterDispositionDepartmentProcessorImpl) buildDispositionStatusResponse(dispositions []entities.LetterIncomingDispositionDepartment) *contract.ListDepartmentDispositionStatusResponse {
|
|
var response []contract.DepartmentDispositionStatusResponse
|
|
|
|
for _, disp := range dispositions {
|
|
response = append(response, *p.buildSingleDispositionStatusResponse(&disp))
|
|
}
|
|
|
|
return &contract.ListDepartmentDispositionStatusResponse{
|
|
Dispositions: response,
|
|
Pagination: contract.PaginationResponse{
|
|
TotalCount: len(response),
|
|
Page: 1,
|
|
Limit: len(response),
|
|
TotalPages: 1,
|
|
},
|
|
}
|
|
}
|
|
|
|
func (p *LetterDispositionDepartmentProcessorImpl) buildSingleDispositionStatusResponse(dispDept *entities.LetterIncomingDispositionDepartment) *contract.DepartmentDispositionStatusResponse {
|
|
letterResp := transformer.LetterIncomingEntityToContract(dispDept.LetterIncoming)
|
|
|
|
var fromDept *contract.DepartmentResponse
|
|
if dispDept.LetterIncomingDisposition != nil && dispDept.LetterIncomingDisposition.DepartmentID != nil {
|
|
fromDept = transformer.DepartmentEntityToContract(&dispDept.LetterIncomingDisposition.Department)
|
|
}
|
|
|
|
return &contract.DepartmentDispositionStatusResponse{
|
|
ID: dispDept.ID,
|
|
LetterID: dispDept.LetterIncomingID,
|
|
Letter: letterResp,
|
|
FromDepartmentID: dispDept.LetterIncomingDisposition.DepartmentID,
|
|
FromDepartment: fromDept,
|
|
ToDepartmentID: dispDept.DepartmentID,
|
|
ToDepartment: transformer.DepartmentEntityToContract(dispDept.Department),
|
|
Status: string(dispDept.Status),
|
|
Notes: dispDept.LetterIncomingDisposition.Notes,
|
|
ReadAt: dispDept.ReadAt,
|
|
CompletedAt: dispDept.CompletedAt,
|
|
CreatedAt: dispDept.CreatedAt,
|
|
UpdatedAt: dispDept.UpdatedAt,
|
|
}
|
|
}
|