From cdc1244efc4b54502ee197a96a52ba6fedfac182 Mon Sep 17 00:00:00 2001 From: efrilm Date: Mon, 13 Oct 2025 03:33:20 +0700 Subject: [PATCH] add priority ids at outgoing letter --- .DS_Store | Bin 8196 -> 6148 bytes internal/contract/letter_outgoing_contract.go | 97 +++++++++--------- internal/handler/letter_outgoing_handler.go | 10 ++ .../repository/letter_outgoing_repository.go | 22 ++-- internal/service/letter_outgoing_service.go | 11 +- 5 files changed, 79 insertions(+), 61 deletions(-) diff --git a/.DS_Store b/.DS_Store index fa91e60ad75a64f00ece6c63b382aa9b4a0cc4f3..1c429845fd371b5bf1776eb7fe56807d74883183 100644 GIT binary patch delta 123 zcmZp1XfcprU|?W$DortDU=RQ@Ie-{Mvv5r;6q~50CiOcRSvFJ|Z95M%~w0s;YUAmIwqzp?N;^JIP*PmpO0Oc0YnhB0i8=b6I{ E08!HwjsO4v delta 528 zcmZoMXmOBWU|?W$DortDU;r^WfEYvza8FDWo2aKKssfS+@);OP8B!QhbJ7iilk+zV za)_~PEa+uk%+A3vv4Eu>q>7zEk0F^MhanMJWo`jb1_+q$0tqw~x%n|#RWTyzO z3|xNO1MCzO6$ocwSApt+2A~D?49pBkKnLU@Th8+7Oc_uPDuZls!rE)qo)%z>;j#!z zF=df0Wcl;~XeiLsWQJUZ6sUchr?M<(+PsG+h?z@*8z}1vidSIVeP^D`FXB1bpNE43 P7`31%XV@IiGlv-fBtvw- diff --git a/internal/contract/letter_outgoing_contract.go b/internal/contract/letter_outgoing_contract.go index 82c5c3d..e842828 100644 --- a/internal/contract/letter_outgoing_contract.go +++ b/internal/contract/letter_outgoing_contract.go @@ -7,19 +7,19 @@ import ( ) type SearchOutgoingLettersRequest struct { - Query string `json:"query" form:"query"` - LetterNumber string `json:"letter_number" form:"letter_number"` - Subject string `json:"subject" form:"subject"` - Status string `json:"status" form:"status"` - PriorityID *uuid.UUID `json:"priority_id" form:"priority_id"` - InstitutionID *uuid.UUID `json:"institution_id" form:"institution_id"` - CreatedBy *uuid.UUID `json:"created_by" form:"created_by"` - DateFrom *time.Time `json:"date_from" form:"date_from"` - DateTo *time.Time `json:"date_to" form:"date_to"` - Page int `json:"page" form:"page"` - Limit int `json:"limit" form:"limit"` - SortBy string `json:"sort_by" form:"sort_by"` - SortOrder string `json:"sort_order" form:"sort_order"` + Query string `json:"query" form:"query"` + LetterNumber string `json:"letter_number" form:"letter_number"` + Subject string `json:"subject" form:"subject"` + Status string `json:"status" form:"status"` + PriorityID *uuid.UUID `json:"priority_id" form:"priority_id"` + InstitutionID *uuid.UUID `json:"institution_id" form:"institution_id"` + CreatedBy *uuid.UUID `json:"created_by" form:"created_by"` + DateFrom *time.Time `json:"date_from" form:"date_from"` + DateTo *time.Time `json:"date_to" form:"date_to"` + Page int `json:"page" form:"page"` + Limit int `json:"limit" form:"limit"` + SortBy string `json:"sort_by" form:"sort_by"` + SortOrder string `json:"sort_order" form:"sort_order"` } type SearchOutgoingLettersResponse struct { @@ -55,7 +55,7 @@ type CreateOutgoingLetterRequest struct { IssueDate time.Time `json:"issue_date" validate:"required"` Attachments []CreateOutgoingLetterAttachment `json:"attachments,omitempty"` UserID uuid.UUID - ApprovalFlowID *uuid.UUID `json:"approval_flow_id,omitempty"` + ApprovalFlowID *uuid.UUID `json:"approval_flow_id,omitempty"` } type OutgoingLetterRecipientResponse struct { @@ -110,7 +110,7 @@ type OutgoingLetterResponse struct { CreatedBy uuid.UUID `json:"created_by"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` - IsRead bool `json:"is_read"` + IsRead bool `json:"is_read"` Recipients []OutgoingLetterRecipientResponse `json:"recipients,omitempty"` Attachments []OutgoingLetterAttachmentResponse `json:"attachments,omitempty"` Approvals []OutgoingLetterApprovalResponse `json:"approvals,omitempty"` @@ -127,20 +127,21 @@ type UpdateOutgoingLetterRequest struct { } type ListOutgoingLettersRequest struct { - Page int `form:"page" json:"page"` - Limit int `form:"limit" json:"limit"` - Status string `form:"status" json:"status,omitempty"` - Query string `form:"q" json:"query,omitempty"` - CreatedBy *uuid.UUID `form:"created_by" json:"created_by,omitempty"` - DepartmentID *uuid.UUID `form:"department_id" json:"department_id,omitempty"` - ReceiverInstitutionID *uuid.UUID `form:"receiver_institution_id" json:"receiver_institution_id,omitempty"` - FromDate string `form:"from_date" json:"from_date,omitempty"` - ToDate string `form:"to_date" json:"to_date,omitempty"` - PriorityID *uuid.UUID `form:"priority_id" json:"priority_id,omitempty"` - SortBy string `form:"sort_by" json:"sort_by,omitempty"` - SortOrder string `form:"sort_order" json:"sort_order,omitempty"` - IsArchived *bool `form:"is_archived" json:"is_archived,omitempty"` - IsRead *bool `form:"is_read,omitempty"` + Page int `form:"page" json:"page"` + Limit int `form:"limit" json:"limit"` + Status string `form:"status" json:"status,omitempty"` + Query string `form:"q" json:"query,omitempty"` + CreatedBy *uuid.UUID `form:"created_by" json:"created_by,omitempty"` + DepartmentID *uuid.UUID `form:"department_id" json:"department_id,omitempty"` + ReceiverInstitutionID *uuid.UUID `form:"receiver_institution_id" json:"receiver_institution_id,omitempty"` + FromDate string `form:"from_date" json:"from_date,omitempty"` + ToDate string `form:"to_date" json:"to_date,omitempty"` + PriorityID *uuid.UUID `form:"priority_id" json:"priority_id,omitempty"` + PriorityIDs []uuid.UUID `json:"priority_ids,omitempty"` + SortBy string `form:"sort_by" json:"sort_by,omitempty"` + SortOrder string `form:"sort_order" json:"sort_order,omitempty"` + IsArchived *bool `form:"is_archived" json:"is_archived,omitempty"` + IsRead *bool `form:"is_read,omitempty"` } type ListOutgoingLettersResponse struct { @@ -245,8 +246,8 @@ type ApprovalFlowStepResponse struct { type ListApprovalFlowsRequest struct { Limit int `json:"limit"` - Page int `json:"page"` - Search *string `json:"search"` + Page int `json:"page"` + Search *string `json:"search"` DepartmentID *uuid.UUID `json:"department_id,omitempty"` IsActive *bool `json:"is_active,omitempty"` } @@ -333,16 +334,16 @@ type OutgoingLetterDiscussionAttachmentResponse struct { // TimelineEvent represents a single event in the approval timeline type TimelineEvent struct { - ID string `json:"id"` - Type string `json:"type"` // "approval", "discussion", "submission", "rejection" - Timestamp time.Time `json:"timestamp"` - Actor *UserResponse `json:"actor,omitempty"` - Action string `json:"action"` - Description string `json:"description"` - Status string `json:"status,omitempty"` - StepOrder int `json:"step_order,omitempty"` - Message string `json:"message,omitempty"` - Data interface{} `json:"data,omitempty"` + ID string `json:"id"` + Type string `json:"type"` // "approval", "discussion", "submission", "rejection" + Timestamp time.Time `json:"timestamp"` + Actor *UserResponse `json:"actor,omitempty"` + Action string `json:"action"` + Description string `json:"description"` + Status string `json:"status,omitempty"` + StepOrder int `json:"step_order,omitempty"` + Message string `json:"message,omitempty"` + Data interface{} `json:"data,omitempty"` } // ApprovalTimelineResponse represents the complete timeline for a letter @@ -358,11 +359,11 @@ type ApprovalTimelineResponse struct { // TimelineSummary provides overview statistics for the timeline type TimelineSummary struct { - TotalSteps int `json:"total_steps"` - CompletedSteps int `json:"completed_steps"` - PendingSteps int `json:"pending_steps"` - CurrentStep int `json:"current_step"` - TotalDuration string `json:"total_duration"` - AverageStepTime string `json:"average_step_time"` - Status string `json:"status"` + TotalSteps int `json:"total_steps"` + CompletedSteps int `json:"completed_steps"` + PendingSteps int `json:"pending_steps"` + CurrentStep int `json:"current_step"` + TotalDuration string `json:"total_duration"` + AverageStepTime string `json:"average_step_time"` + Status string `json:"status"` } diff --git a/internal/handler/letter_outgoing_handler.go b/internal/handler/letter_outgoing_handler.go index 3015a61..3971a30 100644 --- a/internal/handler/letter_outgoing_handler.go +++ b/internal/handler/letter_outgoing_handler.go @@ -102,7 +102,17 @@ func (h *LetterOutgoingHandler) ListOutgoingLetters(c *gin.Context) { req.Limit = 10 } + if ids := c.QueryArray("priority_ids[]"); len(ids) > 0 { + for _, s := range ids { + if id, err := uuid.Parse(s); err == nil { + req.PriorityIDs = append(req.PriorityIDs, id) + } + } + } + fmt.Printf("[DEBUG] request: %v\n", req) + fmt.Printf("[DEBUG] Raw query: %v\n", c.Request.URL.RawQuery) + fmt.Printf("[DEBUG] Parsed form: %v\n", c.Request.URL.Query()) resp, err := h.svc.ListOutgoingLetters(c.Request.Context(), &req) if err != nil { diff --git a/internal/repository/letter_outgoing_repository.go b/internal/repository/letter_outgoing_repository.go index 6813893..b302026 100644 --- a/internal/repository/letter_outgoing_repository.go +++ b/internal/repository/letter_outgoing_repository.go @@ -91,6 +91,7 @@ type ListOutgoingLettersFilter struct { FromDate *time.Time ToDate *time.Time PriorityID *uuid.UUID + PriorityIDs []uuid.UUID SortBy *string SortOrder *string IsArchived *bool @@ -127,7 +128,7 @@ func (r *LetterOutgoingRepository) List(ctx context.Context, filter ListOutgoing fmt.Printf("[DEBUG] filter.UserID: %v\n", filter.UserID) fmt.Printf("[DEBUG] filter.isRead: %v\n", filter.IsRead) - + // Tambahkan filter IsRead if filter.IsRead != nil { if *filter.IsRead { @@ -136,17 +137,20 @@ func (r *LetterOutgoingRepository) List(ctx context.Context, filter ListOutgoing query = query.Where("letter_outgoing_recipients.read_at IS NULL") } } - + query = query.Distinct() } - if filter.ReceiverInstitutionID != nil { query = query.Where("receiver_institution_id = ?", *filter.ReceiverInstitutionID) } if filter.PriorityID != nil { query = query.Where("priority_id = ?", *filter.PriorityID) } + if len(filter.PriorityIDs) > 0 { + query = query.Where("priority_id IN ?", filter.PriorityIDs) + } + fmt.Printf("Priority %s", filter.PriorityIDs) if filter.FromDate != nil { query = query.Where("issue_date >= ?", *filter.FromDate) } @@ -351,19 +355,19 @@ func (r *LetterOutgoingAttachmentRepository) ListByLetterIDs(ctx context.Context if len(letterIDs) == 0 { return make(map[uuid.UUID][]entities.LetterOutgoingAttachment), nil } - + db := DBFromContext(ctx, r.db) var attachments []entities.LetterOutgoingAttachment if err := db.WithContext(ctx).Where("letter_id IN ?", letterIDs).Order("uploaded_at ASC").Find(&attachments).Error; err != nil { return nil, err } - + // Group attachments by letter ID result := make(map[uuid.UUID][]entities.LetterOutgoingAttachment) for _, att := range attachments { result[att.LetterID] = append(result[att.LetterID], att) } - + return result, nil } @@ -441,7 +445,7 @@ func (r *LetterOutgoingRecipientRepository) ListByLetterIDs(ctx context.Context, if len(letterIDs) == 0 { return make(map[uuid.UUID][]entities.LetterOutgoingRecipient), nil } - + db := DBFromContext(ctx, r.db) var recipients []entities.LetterOutgoingRecipient if err := db.WithContext(ctx). @@ -453,13 +457,13 @@ func (r *LetterOutgoingRecipientRepository) ListByLetterIDs(ctx context.Context, Find(&recipients).Error; err != nil { return nil, err } - + // Group recipients by letter ID result := make(map[uuid.UUID][]entities.LetterOutgoingRecipient) for _, rec := range recipients { result[rec.LetterID] = append(result[rec.LetterID], rec) } - + return result, nil } diff --git a/internal/service/letter_outgoing_service.go b/internal/service/letter_outgoing_service.go index c5e01c6..a9a74eb 100644 --- a/internal/service/letter_outgoing_service.go +++ b/internal/service/letter_outgoing_service.go @@ -211,6 +211,7 @@ func (s *LetterOutgoingServiceImpl) ListOutgoingLetters(ctx context.Context, req DepartmentID: req.DepartmentID, ReceiverInstitutionID: req.ReceiverInstitutionID, PriorityID: req.PriorityID, + PriorityIDs: req.PriorityIDs, UserID: &userID, IsRead: req.IsRead, } @@ -219,6 +220,10 @@ func (s *LetterOutgoingServiceImpl) ListOutgoingLetters(ctx context.Context, req filter.DepartmentID = &departmentID } + if len(req.PriorityIDs) > 0 { + filter.PriorityIDs = req.PriorityIDs + } + if req.Status != "" { filter.Status = &req.Status } @@ -300,7 +305,6 @@ func (s *LetterOutgoingServiceImpl) ListOutgoingLetters(ctx context.Context, req result := batchResult{} errChan := make(chan error, 4) - // Load attachments go func() { @@ -308,7 +312,7 @@ func (s *LetterOutgoingServiceImpl) ListOutgoingLetters(ctx context.Context, req errChan <- err }() - // Load recipients + // Load recipients go func() { result.recipients, err = s.processor.GetBatchRecipients(ctx, letterIDs) errChan <- err @@ -366,7 +370,6 @@ func (s *LetterOutgoingServiceImpl) ListOutgoingLetters(ctx context.Context, req if recipient, exists := recipientByUser[letter.ID]; exists && recipient != nil { isRead = recipient.ReadAt != nil } - response := transformLetterToResponse(&letter) response.IsRead = isRead @@ -1906,4 +1909,4 @@ func (s *LetterOutgoingServiceImpl) extractUserIDsFromMentions(mentions map[stri } return userIDs -} \ No newline at end of file +}