implement archived
This commit is contained in:
parent
ca2acfd850
commit
90da195a2e
@ -54,15 +54,15 @@ type LetterOutgoingService interface {
|
||||
}
|
||||
|
||||
type LetterOutgoingServiceImpl struct {
|
||||
processor processor.LetterOutgoingProcessor
|
||||
txManager *repository.TxManager
|
||||
validationProcessor processor.LetterValidationProcessor
|
||||
creationProcessor processor.LetterCreationProcessor
|
||||
approvalProcessor processor.LetterApprovalProcessor
|
||||
attachmentProcessor processor.LetterAttachmentProcessor
|
||||
recipientProcessor processor.LetterOutgoingRecipientProcessor
|
||||
processor processor.LetterOutgoingProcessor
|
||||
txManager *repository.TxManager
|
||||
validationProcessor processor.LetterValidationProcessor
|
||||
creationProcessor processor.LetterCreationProcessor
|
||||
approvalProcessor processor.LetterApprovalProcessor
|
||||
attachmentProcessor processor.LetterAttachmentProcessor
|
||||
recipientProcessor processor.LetterOutgoingRecipientProcessor
|
||||
notificationProcessor processor.NotificationProcessor
|
||||
activityProcessor processor.LetterActivityProcessor
|
||||
activityProcessor processor.LetterActivityProcessor
|
||||
}
|
||||
|
||||
func NewLetterOutgoingService(
|
||||
@ -77,15 +77,15 @@ func NewLetterOutgoingService(
|
||||
activityProcessor processor.LetterActivityProcessor,
|
||||
) *LetterOutgoingServiceImpl {
|
||||
return &LetterOutgoingServiceImpl{
|
||||
processor: processor,
|
||||
txManager: txManager,
|
||||
validationProcessor: validationProcessor,
|
||||
creationProcessor: creationProcessor,
|
||||
approvalProcessor: approvalProcessor,
|
||||
attachmentProcessor: attachmentProcessor,
|
||||
recipientProcessor: recipientProcessor,
|
||||
processor: processor,
|
||||
txManager: txManager,
|
||||
validationProcessor: validationProcessor,
|
||||
creationProcessor: creationProcessor,
|
||||
approvalProcessor: approvalProcessor,
|
||||
attachmentProcessor: attachmentProcessor,
|
||||
recipientProcessor: recipientProcessor,
|
||||
notificationProcessor: notificationProcessor,
|
||||
activityProcessor: activityProcessor,
|
||||
activityProcessor: activityProcessor,
|
||||
}
|
||||
}
|
||||
|
||||
@ -172,7 +172,7 @@ func (s *LetterOutgoingServiceImpl) CreateOutgoingLetter(ctx context.Context, re
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Send notifications if letter needs approval
|
||||
// Send notifications if letter needs approval
|
||||
log.Printf("[DEBUG] createOutgoingLetter Finsig")
|
||||
log.Printf("[DEBUG] NotificationProcessor is nil: %v", s.notificationProcessor == nil)
|
||||
if s.notificationProcessor != nil && len(result.Approvals) > 0 {
|
||||
@ -180,7 +180,6 @@ func (s *LetterOutgoingServiceImpl) CreateOutgoingLetter(ctx context.Context, re
|
||||
go s.sendStepApprovalNotifications(context.Background(), result.ID, result.Subject, 1)
|
||||
}
|
||||
|
||||
|
||||
return transformLetterToResponse(result), nil
|
||||
}
|
||||
|
||||
@ -242,7 +241,11 @@ func (s *LetterOutgoingServiceImpl) ListOutgoingLetters(ctx context.Context, req
|
||||
}
|
||||
}
|
||||
|
||||
filter.IsArchived = req.IsArchived
|
||||
archived := true
|
||||
filter.IsArchived = &archived
|
||||
if filter.IsArchived != nil {
|
||||
filter.IsArchived = req.IsArchived
|
||||
}
|
||||
|
||||
// Get raw letters data
|
||||
letters, total, err := s.processor.ListOutgoingLetters(ctx, filter, req.Limit, offset)
|
||||
@ -254,7 +257,7 @@ func (s *LetterOutgoingServiceImpl) ListOutgoingLetters(ctx context.Context, req
|
||||
letterIDs := make([]uuid.UUID, len(letters))
|
||||
priorityIDs := make(map[uuid.UUID]bool)
|
||||
institutionIDs := make(map[uuid.UUID]bool)
|
||||
|
||||
|
||||
for i, letter := range letters {
|
||||
letterIDs[i] = letter.ID
|
||||
if letter.PriorityID != nil {
|
||||
@ -270,7 +273,7 @@ func (s *LetterOutgoingServiceImpl) ListOutgoingLetters(ctx context.Context, req
|
||||
for id := range priorityIDs {
|
||||
priorityIDSlice = append(priorityIDSlice, id)
|
||||
}
|
||||
|
||||
|
||||
institutionIDSlice := make([]uuid.UUID, 0, len(institutionIDs))
|
||||
for id := range institutionIDs {
|
||||
institutionIDSlice = append(institutionIDSlice, id)
|
||||
@ -287,31 +290,31 @@ func (s *LetterOutgoingServiceImpl) ListOutgoingLetters(ctx context.Context, req
|
||||
|
||||
result := batchResult{}
|
||||
errChan := make(chan error, 4)
|
||||
|
||||
|
||||
// Load attachments
|
||||
go func() {
|
||||
result.attachments, err = s.processor.GetBatchAttachments(ctx, letterIDs)
|
||||
errChan <- err
|
||||
}()
|
||||
|
||||
|
||||
// Load recipients
|
||||
go func() {
|
||||
result.recipients, err = s.processor.GetBatchRecipients(ctx, letterIDs)
|
||||
errChan <- err
|
||||
}()
|
||||
|
||||
|
||||
// Load priorities
|
||||
go func() {
|
||||
result.priorities, err = s.processor.GetBatchPriorities(ctx, priorityIDSlice)
|
||||
errChan <- err
|
||||
}()
|
||||
|
||||
|
||||
// Load institutions
|
||||
go func() {
|
||||
result.institutions, err = s.processor.GetBatchInstitutions(ctx, institutionIDSlice)
|
||||
errChan <- err
|
||||
}()
|
||||
|
||||
|
||||
// Wait for all goroutines and check for errors
|
||||
for i := 0; i < 4; i++ {
|
||||
if err := <-errChan; err != nil {
|
||||
@ -339,7 +342,7 @@ func (s *LetterOutgoingServiceImpl) ListOutgoingLetters(ctx context.Context, req
|
||||
letter.ReceiverInstitution = institution
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
items[i] = transformLetterToResponse(&letter)
|
||||
}
|
||||
|
||||
@ -479,12 +482,12 @@ func (s *LetterOutgoingServiceImpl) ApproveOutgoingLetter(ctx context.Context, l
|
||||
if s.notificationProcessor != nil {
|
||||
// Step approved but not final - notify creator about step completion AND next approvers
|
||||
creatorMessage := fmt.Sprintf("Surat keluar '%s' telah disetujui pada tahap %d, menunggu persetujuan tahap berikutnya", letter.Subject, currentApproval.StepOrder)
|
||||
go s.sendApprovalNotificationToCreator(context.Background(), letterID, letter.CreatedBy, "Surat Keluar Disetujui Tahap " + fmt.Sprintf("%d", currentApproval.StepOrder), creatorMessage)
|
||||
|
||||
go s.sendApprovalNotificationToCreator(context.Background(), letterID, letter.CreatedBy, "Surat Keluar Disetujui Tahap "+fmt.Sprintf("%d", currentApproval.StepOrder), creatorMessage)
|
||||
|
||||
// Notify next step approvers
|
||||
nextStepOrder := currentApproval.StepOrder + 1
|
||||
go s.sendStepApprovalNotifications(context.Background(), letterID, letter.Subject, nextStepOrder)
|
||||
|
||||
|
||||
}
|
||||
|
||||
return nil
|
||||
@ -734,7 +737,6 @@ func (s *LetterOutgoingServiceImpl) CreateDiscussion(ctx context.Context, letter
|
||||
go s.sendOutgoingDiscussionMentionNotifications(context.Background(), letterID, userID, req.Mentions, req.Message)
|
||||
}
|
||||
|
||||
|
||||
return transformDiscussionToResponse(result), nil
|
||||
}
|
||||
|
||||
@ -1390,7 +1392,7 @@ func (s *LetterOutgoingServiceImpl) GetApprovalTimeline(ctx context.Context, let
|
||||
eventType := "approval"
|
||||
action := "approved"
|
||||
status := "approved"
|
||||
|
||||
|
||||
if approval.Status == "rejected" {
|
||||
eventType = "rejection"
|
||||
action = "rejected"
|
||||
@ -1399,7 +1401,7 @@ func (s *LetterOutgoingServiceImpl) GetApprovalTimeline(ctx context.Context, let
|
||||
continue // Skip pending approvals as they haven't happened yet
|
||||
}
|
||||
|
||||
description := fmt.Sprintf("Step %d: %s by %s",
|
||||
description := fmt.Sprintf("Step %d: %s by %s",
|
||||
approval.StepOrder,
|
||||
action,
|
||||
getApproverName(approval.Approver))
|
||||
@ -1461,7 +1463,7 @@ func (s *LetterOutgoingServiceImpl) calculateTimelineSummary(
|
||||
completedSteps := 0
|
||||
pendingSteps := 0
|
||||
currentStep := 0
|
||||
|
||||
|
||||
// Count unique step orders
|
||||
stepMap := make(map[int]string)
|
||||
for _, approval := range approvals {
|
||||
@ -1469,7 +1471,7 @@ func (s *LetterOutgoingServiceImpl) calculateTimelineSummary(
|
||||
stepMap[approval.StepOrder] = approval.Status
|
||||
totalSteps++
|
||||
}
|
||||
|
||||
|
||||
switch approval.Status {
|
||||
case "approved":
|
||||
if stepMap[approval.StepOrder] == "approved" {
|
||||
@ -1487,12 +1489,12 @@ func (s *LetterOutgoingServiceImpl) calculateTimelineSummary(
|
||||
// Calculate duration
|
||||
totalDuration := ""
|
||||
averageStepTime := ""
|
||||
|
||||
|
||||
if len(timeline) > 0 {
|
||||
lastEvent := timeline[len(timeline)-1]
|
||||
duration := lastEvent.Timestamp.Sub(letter.CreatedAt)
|
||||
totalDuration = formatDuration(duration)
|
||||
|
||||
|
||||
if completedSteps > 0 {
|
||||
avgDuration := duration / time.Duration(completedSteps)
|
||||
averageStepTime = formatDuration(avgDuration)
|
||||
@ -1548,7 +1550,7 @@ func formatDuration(d time.Duration) string {
|
||||
days := int(d.Hours() / 24)
|
||||
hours := int(d.Hours()) % 24
|
||||
minutes := int(d.Minutes()) % 60
|
||||
|
||||
|
||||
if days > 0 {
|
||||
return fmt.Sprintf("%dd %dh %dm", days, hours, minutes)
|
||||
} else if hours > 0 {
|
||||
@ -1578,7 +1580,7 @@ func (s *LetterOutgoingServiceImpl) BulkArchiveOutgoingLetters(ctx context.Conte
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
||||
return &contract.BulkArchiveLettersResponse{
|
||||
Success: true,
|
||||
Message: "Letters archived successfully",
|
||||
@ -1588,7 +1590,7 @@ func (s *LetterOutgoingServiceImpl) BulkArchiveOutgoingLetters(ctx context.Conte
|
||||
|
||||
func (s *LetterOutgoingServiceImpl) sendStepApprovalNotifications(ctx context.Context, letterID uuid.UUID, subject string, stepOrder int) {
|
||||
log.Printf("[DEBUG] sendStepApprovalNotifications START - LetterID: %s, StepOrder: %d", letterID.String(), stepOrder)
|
||||
|
||||
|
||||
approvals, err := s.processor.GetApprovalsByLetter(ctx, letterID)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Failed to get approvals: %v", err)
|
||||
@ -1596,15 +1598,15 @@ func (s *LetterOutgoingServiceImpl) sendStepApprovalNotifications(ctx context.Co
|
||||
}
|
||||
|
||||
log.Printf("[DEBUG] Found %d approvals", len(approvals))
|
||||
|
||||
|
||||
// Find approvers for the specified step
|
||||
for _, approval := range approvals {
|
||||
log.Printf("[DEBUG] Checking approval: Step=%d, Status=%s, ApproverID=%v",
|
||||
log.Printf("[DEBUG] Checking approval: Step=%d, Status=%s, ApproverID=%v",
|
||||
approval.StepOrder, approval.Status, approval.ApproverID)
|
||||
|
||||
if approval.StepOrder == stepOrder {
|
||||
|
||||
if approval.StepOrder == stepOrder {
|
||||
log.Printf("[DEBUG] Sending notification to approver %s for step %d", approval.ApproverID.String(), stepOrder)
|
||||
|
||||
|
||||
err := s.notificationProcessor.SendOutgoingLetterNotification(
|
||||
ctx,
|
||||
letterID,
|
||||
@ -1624,7 +1626,7 @@ func (s *LetterOutgoingServiceImpl) sendStepApprovalNotifications(ctx context.Co
|
||||
// Kirim notifikasi ke creator
|
||||
func (s *LetterOutgoingServiceImpl) sendApprovalNotificationToCreator(ctx context.Context, letterID uuid.UUID, creatorID uuid.UUID, title string, message string) {
|
||||
log.Printf("[DEBUG] sendApprovalNotificationToCreator START - LetterID: %s, CreatorID: %s", letterID.String(), creatorID.String())
|
||||
|
||||
|
||||
err := s.notificationProcessor.SendOutgoingLetterNotification(
|
||||
ctx,
|
||||
letterID,
|
||||
@ -1641,47 +1643,47 @@ func (s *LetterOutgoingServiceImpl) sendApprovalNotificationToCreator(ctx contex
|
||||
|
||||
func (s *LetterOutgoingServiceImpl) sendOutgoingDiscussionMentionNotifications(ctx context.Context, letterID uuid.UUID, senderUserID uuid.UUID, mentions map[string]interface{}, message string) {
|
||||
log.Printf("[DEBUG] sendOutgoingDiscussionMentionNotifications START - LetterID: %s", letterID.String())
|
||||
|
||||
|
||||
// Extract user_ids dari mentions
|
||||
userIDs := s.extractUserIDsFromMentions(mentions)
|
||||
if len(userIDs) == 0 {
|
||||
log.Printf("[DEBUG] No user IDs found in mentions")
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
log.Printf("[DEBUG] Found %d mentioned users", len(userIDs))
|
||||
|
||||
|
||||
// Get letter details untuk notification
|
||||
letter, err := s.processor.GetOutgoingLetterByID(ctx, letterID)
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Failed to get letter details: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
// Get sender user name dari context (bisa juga dari user service)
|
||||
appContext := appcontext.FromGinContext(ctx)
|
||||
senderName := appContext.UserName
|
||||
if senderName == "" {
|
||||
senderName = "Seseorang" // fallback jika nama tidak tersedia
|
||||
}
|
||||
|
||||
|
||||
// Kirim notification ke setiap mentioned user
|
||||
for _, mentionedUserID := range userIDs {
|
||||
// Jangan kirim notification ke sender sendiri
|
||||
if mentionedUserID == senderUserID {
|
||||
continue
|
||||
}
|
||||
|
||||
|
||||
subject := "Anda Disebutkan dalam Diskusi Surat Keluar"
|
||||
notificationMessage := fmt.Sprintf("%s menyebutkan Anda dalam diskusi surat keluar: %s", senderName, letter.Subject)
|
||||
|
||||
|
||||
err := s.notificationProcessor.SendOutgoingLetterNotification(
|
||||
ctx,
|
||||
letterID,
|
||||
mentionedUserID,
|
||||
subject,
|
||||
notificationMessage)
|
||||
|
||||
|
||||
if err != nil {
|
||||
log.Printf("[ERROR] Failed to send mention notification to user %s: %v", mentionedUserID.String(), err)
|
||||
} else {
|
||||
@ -1693,11 +1695,11 @@ func (s *LetterOutgoingServiceImpl) sendOutgoingDiscussionMentionNotifications(c
|
||||
// Helper function untuk extract user IDs dari mentions map
|
||||
func (s *LetterOutgoingServiceImpl) extractUserIDsFromMentions(mentions map[string]interface{}) []uuid.UUID {
|
||||
userIDs := make([]uuid.UUID, 0)
|
||||
|
||||
|
||||
if mentions == nil {
|
||||
return userIDs
|
||||
}
|
||||
|
||||
|
||||
if userIDsInterface, exists := mentions["user_ids"]; exists {
|
||||
switch userIDsValue := userIDsInterface.(type) {
|
||||
case []interface{}:
|
||||
@ -1718,6 +1720,6 @@ func (s *LetterOutgoingServiceImpl) extractUserIDsFromMentions(mentions map[stri
|
||||
userIDs = userIDsValue
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return userIDs
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user