252 lines
8.0 KiB
Go
252 lines
8.0 KiB
Go
package processor
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"eslogad-be/internal/appcontext"
|
|
"eslogad-be/internal/contract"
|
|
"eslogad-be/internal/entities"
|
|
"eslogad-be/internal/transformer"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
func (p *LetterProcessorImpl) GetDepartmentDispositionStatus(ctx context.Context, req *contract.GetDepartmentDispositionStatusRequest) (*contract.ListDepartmentDispositionStatusResponse, error) {
|
|
dispositions, err := p.dispositionDeptRepo.GetByLetterIncomingID(ctx, req.LetterIncomingID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var response []contract.DepartmentDispositionStatusResponse
|
|
for _, disp := range dispositions {
|
|
letterResp := transformer.LetterIncomingEntityToContract(disp.LetterIncoming)
|
|
|
|
var fromDept *contract.DepartmentResponse
|
|
if disp.LetterIncomingDisposition != nil && disp.LetterIncomingDisposition.DepartmentID != nil {
|
|
fromDept = transformer.DepartmentEntityToContract(&disp.LetterIncomingDisposition.Department)
|
|
}
|
|
|
|
response = append(response, contract.DepartmentDispositionStatusResponse{
|
|
ID: disp.ID,
|
|
LetterID: disp.LetterIncomingID,
|
|
Letter: letterResp,
|
|
FromDepartmentID: disp.LetterIncomingDisposition.DepartmentID,
|
|
FromDepartment: fromDept,
|
|
ToDepartmentID: disp.DepartmentID,
|
|
ToDepartment: transformer.DepartmentEntityToContract(disp.Department),
|
|
Status: string(disp.Status),
|
|
Notes: disp.LetterIncomingDisposition.Notes,
|
|
ReadAt: disp.ReadAt,
|
|
CompletedAt: disp.CompletedAt,
|
|
CreatedAt: disp.CreatedAt,
|
|
UpdatedAt: disp.UpdatedAt,
|
|
})
|
|
}
|
|
|
|
return &contract.ListDepartmentDispositionStatusResponse{
|
|
Dispositions: response,
|
|
Pagination: contract.PaginationResponse{
|
|
TotalCount: len(response),
|
|
Page: 1,
|
|
Limit: len(response),
|
|
TotalPages: 1,
|
|
},
|
|
}, nil
|
|
}
|
|
|
|
func (p *LetterProcessorImpl) UpdateDispositionStatus(ctx context.Context, req *contract.UpdateDispositionStatusRequest) (*contract.DepartmentDispositionStatusResponse, error) {
|
|
var result *contract.DepartmentDispositionStatusResponse
|
|
|
|
err := p.txManager.WithTransaction(ctx, func(txCtx context.Context) error {
|
|
userID := appcontext.FromGinContext(txCtx).UserID
|
|
departmentID := appcontext.FromGinContext(txCtx).DepartmentID
|
|
|
|
dispDept, err := p.dispositionDeptRepo.GetByDispositionAndDepartment(txCtx, req.LetterIncomingID, departmentID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
notes := ""
|
|
if req.Notes != nil {
|
|
notes = *req.Notes
|
|
}
|
|
if err := p.updateDispositionDepartmentStatus(txCtx, dispDept.ID, req.Status, notes); err != nil {
|
|
return err
|
|
}
|
|
|
|
p.activity.LogLetterDispositionStatusUpdate(txCtx, req.LetterIncomingID, userID, req.Status)
|
|
|
|
if err := p.checkAndUpdateLetterCompletionStatus(txCtx, req.LetterIncomingID); err != nil {
|
|
return err
|
|
}
|
|
|
|
updatedDispDept, err := p.dispositionDeptRepo.GetByID(txCtx, dispDept.ID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
result = p.buildDispositionStatusResponse(updatedDispDept)
|
|
return nil
|
|
})
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
// updateDispositionDepartmentStatus updates the status of a disposition department
|
|
func (p *LetterProcessorImpl) updateDispositionDepartmentStatus(ctx context.Context, dispDeptID uuid.UUID, status, notes string) error {
|
|
now := time.Now()
|
|
var dispositionStatus entities.LetterIncomingDispositionDepartmentStatus
|
|
var readAt, completedAt *time.Time
|
|
|
|
switch status {
|
|
case "completed":
|
|
dispositionStatus = entities.DispositionDepartmentStatusCompleted
|
|
completedAt = &now
|
|
readAt = &now // Mark as read when completing
|
|
case "read":
|
|
dispositionStatus = entities.DispositionDepartmentStatusRead
|
|
readAt = &now
|
|
default:
|
|
dispositionStatus = entities.DispositionDepartmentStatusPending
|
|
}
|
|
|
|
return p.dispositionDeptRepo.UpdateStatus(ctx, dispDeptID, dispositionStatus, notes, readAt, completedAt)
|
|
}
|
|
|
|
// addDispositionNoteIfProvided adds a note to the disposition if provided
|
|
func (p *LetterProcessorImpl) addDispositionNoteIfProvided(ctx context.Context, dispositionID uuid.UUID, userID uuid.UUID, notes *string) error {
|
|
if notes == nil || *notes == "" {
|
|
return nil
|
|
}
|
|
|
|
note := &entities.DispositionNote{
|
|
DispositionID: dispositionID,
|
|
UserID: &userID,
|
|
Note: *notes,
|
|
}
|
|
|
|
return p.dispositionNoteRepo.Create(ctx, note)
|
|
}
|
|
|
|
func (p *LetterProcessorImpl) checkAndUpdateLetterCompletionStatus(ctx context.Context, letterIncomingID uuid.UUID) error {
|
|
dispositions, err := p.dispositionDeptRepo.GetByLetterIncomingID(ctx, letterIncomingID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
allCompleted := true
|
|
for _, disp := range dispositions {
|
|
if disp.Status == entities.DispositionDepartmentStatusPending {
|
|
allCompleted = false
|
|
break
|
|
}
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
// buildDispositionStatusResponse builds the response for disposition status
|
|
func (p *LetterProcessorImpl) buildDispositionStatusResponse(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,
|
|
}
|
|
}
|
|
|
|
func (p *LetterProcessorImpl) GetLetterCTA(ctx context.Context, letterIncomingID uuid.UUID, departmentID uuid.UUID) (*contract.LetterCTAResponse, error) {
|
|
letter, err := p.letterRepo.GetByID(ctx, letterIncomingID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
response := &contract.LetterCTAResponse{
|
|
LetterIncomingID: letterIncomingID,
|
|
Actions: []contract.LetterCTAAction{},
|
|
Message: "",
|
|
}
|
|
|
|
isEligibleForDispo, err := p.dispoRoutes.IsEligibleForDisposition(ctx, departmentID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if letter.Status == "completed" || letter.Status == "archived" {
|
|
response.Message = "Letter is no longer accepting actions"
|
|
return response, nil
|
|
}
|
|
|
|
dispDepts, err := p.dispositionDeptRepo.GetByLetterAndDepartment(ctx, letterIncomingID, departmentID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if len(dispDepts) == 0 {
|
|
response.Message = "Your department is not a recipient of this letter"
|
|
return response, nil
|
|
}
|
|
|
|
for _, dispDept := range dispDepts {
|
|
if dispDept.Status == entities.DispositionDepartmentStatusPending {
|
|
response.DispositionID = &dispDept.LetterIncomingDispositionID
|
|
currentStatus := string(dispDept.Status)
|
|
response.CurrentStatus = ¤tStatus
|
|
|
|
if isEligibleForDispo {
|
|
response.Actions = append(response.Actions, contract.LetterCTAAction{
|
|
Type: "create_disposition",
|
|
Label: "Disposisi",
|
|
Path: fmt.Sprintf("/api/v1/letters/%s/dispositions", letterIncomingID),
|
|
Method: "POST",
|
|
Description: "Create a new disposition for this letter",
|
|
})
|
|
}
|
|
|
|
response.Actions = append(response.Actions, contract.LetterCTAAction{
|
|
Type: "update_status",
|
|
Label: "Tindak Lanjut",
|
|
Path: fmt.Sprintf("/api/v1/letters/dispositions/%s/status", response.LetterIncomingID),
|
|
Method: "PUT",
|
|
Description: "Update the status of your disposition",
|
|
})
|
|
}
|
|
}
|
|
|
|
return response, nil
|
|
}
|