diff --git a/internal/appcontext/context_info.go b/internal/appcontext/context_info.go index df450ec..b741c15 100644 --- a/internal/appcontext/context_info.go +++ b/internal/appcontext/context_info.go @@ -2,6 +2,7 @@ package appcontext import ( "context" + "github.com/google/uuid" "github.com/sirupsen/logrus" ) @@ -48,6 +49,7 @@ func NewAppContext(ctx context.Context, info *ContextInfo) context.Context { "platform": info.Platform, "device_os": info.DeviceOS, "user_locale": info.UserLocale, + "user_role": info.UserRole, }) return context.WithValue(ctx, ctxKey, info) } diff --git a/internal/middleware/auth_middleware.go b/internal/middleware/auth_middleware.go index 7d030b3..6271096 100644 --- a/internal/middleware/auth_middleware.go +++ b/internal/middleware/auth_middleware.go @@ -42,6 +42,7 @@ func (m *AuthMiddleware) RequireAuth() gin.HandlerFunc { setKeyInContext(c, appcontext.UserIDKey, userResponse.ID.String()) setKeyInContext(c, appcontext.UserNameKey, userResponse.Name) + if len(userResponse.DepartmentResponse) > 0 { departmentID := userResponse.DepartmentResponse[0].ID.String() setKeyInContext(c, appcontext.DepartmentIDKey, departmentID) @@ -49,6 +50,13 @@ func (m *AuthMiddleware) RequireAuth() gin.HandlerFunc { setKeyInContext(c, appcontext.DepartmentIDKey, "") } + if len(userResponse.Roles) > 0 { + userRole := userResponse.Roles[0].Code + setKeyInContext(c, appcontext.UserRoleKey, userRole) + } else { + setKeyInContext(c, appcontext.UserRoleKey, "") + } + if roles, perms, err := m.authService.ExtractAccess(token); err == nil { c.Set("user_roles", roles) c.Set("user_permissions", perms) diff --git a/internal/processor/letter_outgoing_processor.go b/internal/processor/letter_outgoing_processor.go index 6ca0755..17780c3 100644 --- a/internal/processor/letter_outgoing_processor.go +++ b/internal/processor/letter_outgoing_processor.go @@ -2,6 +2,7 @@ package processor import ( "context" + "eslogad-be/internal/appcontext" "fmt" "sort" "time" @@ -310,6 +311,16 @@ func (p *LetterOutgoingProcessorImpl) GetOutgoingLetterByID(ctx context.Context, } func (p *LetterOutgoingProcessorImpl) ListOutgoingLetters(ctx context.Context, filter repository.ListOutgoingLettersFilter, limit, offset int) ([]entities.LetterOutgoing, int64, error) { + appCtx := appcontext.FromGinContext(ctx) + + fmt.Printf("Checked User Role: %s\n", appCtx.UserRole) + fmt.Printf("Checked User ID: %s\n", appCtx.UserID) + + if appCtx.IsSuperAdmin() { + fmt.Println("Checked Role: super admin") + return p.letterRepo.ListAll(ctx, filter, limit, offset) + } + return p.letterRepo.List(ctx, filter, limit, offset) } diff --git a/internal/processor/letter_processor.go b/internal/processor/letter_processor.go index d8d268b..6892960 100644 --- a/internal/processor/letter_processor.go +++ b/internal/processor/letter_processor.go @@ -206,6 +206,16 @@ func (p *LetterProcessorImpl) MarkOutgoingLetterAsRead(ctx context.Context, lett func (p *LetterProcessorImpl) ListIncomingLetters(ctx context.Context, filter repository.ListIncomingLettersFilter, page, limit int) ([]entities.LetterIncoming, int64, error) { // Just fetch the raw data + appCtx := appcontext.FromGinContext(ctx) + + fmt.Printf("Checked User Role: %s\n", appCtx.UserRole) + fmt.Printf("Checked User ID: %s\n", appCtx.UserID) + + if appCtx.IsSuperAdmin() { + fmt.Println("Checked Role: super admin") + return p.letterRepo.ListAll(ctx, filter, page, limit) + } + return p.letterRepo.List(ctx, filter, limit, (page-1)*limit) } diff --git a/internal/repository/letter_outgoing_repository.go b/internal/repository/letter_outgoing_repository.go index e5df114..5d7a23d 100644 --- a/internal/repository/letter_outgoing_repository.go +++ b/internal/repository/letter_outgoing_repository.go @@ -260,6 +260,108 @@ func (r *LetterOutgoingRepository) List(ctx context.Context, filter ListOutgoing return list, total, nil } +func (r *LetterOutgoingRepository) ListAll(ctx context.Context, filter ListOutgoingLettersFilter, limit, offset int) ([]entities.LetterOutgoing, int64, error) { + db := DBFromContext(ctx, r.db) + query := db.WithContext(ctx).Model(&entities.LetterOutgoing{}).Where("deleted_at IS NULL") + + // Apply search query filter + if filter.Query != nil { + q := "%" + *filter.Query + "%" + query = query.Where("subject ILIKE ? OR reference_number ILIKE ? OR letter_number ILIKE ?", q, q, q) + } + + // Filter by creator (if admin wants to see letters from specific creator) + if filter.CreatedBy != nil { + query = query.Where("created_by = ?", *filter.CreatedBy) + } + + // Filter by receiver institution + if filter.ReceiverInstitutionID != nil { + query = query.Where("receiver_institution_id = ?", *filter.ReceiverInstitutionID) + } + + // Filter by priority + if filter.PriorityID != nil { + query = query.Where("priority_id = ?", *filter.PriorityID) + } + + // Filter by multiple priorities + if len(filter.PriorityIDs) > 0 { + query = query.Where("priority_id IN ?", filter.PriorityIDs) + } + + // Date range filters + if filter.FromDate != nil { + query = query.Where("issue_date >= ?", *filter.FromDate) + } + if filter.ToDate != nil { + query = query.Where("issue_date <= ?", *filter.ToDate) + } + + // Filter by approval status (if admin wants to see letters with specific approval status) + // Note: This is different from user-specific approval status + if filter.Status != nil { + query = query.Joins("LEFT JOIN letter_outgoing_approvals ON letter_outgoing_approvals.letter_id = letters_outgoing.id"). + Where("letter_outgoing_approvals.status = ?", *filter.Status). + Distinct() + } + + // Get total count + var total int64 + if err := query.Count(&total).Error; err != nil { + return nil, 0, err + } + + // Prepare sorting + orderBy := "created_at DESC" // default + if filter.SortBy != nil { + sortField := *filter.SortBy + sortDirection := "ASC" + if filter.SortOrder != nil && (*filter.SortOrder == "desc" || *filter.SortOrder == "DESC") { + sortDirection = "DESC" + } + + switch sortField { + case "letter_number": + orderBy = "letter_number " + sortDirection + case "subject": + orderBy = "subject " + sortDirection + case "issue_date": + orderBy = "issue_date " + sortDirection + case "status": + orderBy = "status " + sortDirection + case "created_at": + orderBy = "created_at " + sortDirection + default: + orderBy = "created_at " + sortDirection + } + } + + // Get paginated data with all relations + var list []entities.LetterOutgoing + if err := query. + Preload("Priority"). + Preload("ReceiverInstitution"). + Preload("Creator"). + Preload("Creator.Profile"). + Preload("Creator.Departments"). + Preload("Recipients"). + Preload("Recipients.User"). + Preload("Recipients.Department"). + Preload("Attachments"). + Preload("Approvals"). + Preload("Approvals.Step"). + Preload("Approvals.Approver"). + Order(orderBy). + Limit(limit). + Offset(offset). + Find(&list).Error; err != nil { + return nil, 0, err + } + + return list, total, nil +} + func (r *LetterOutgoingRepository) Search(ctx context.Context, filters map[string]interface{}, limit, offset int, sortBy, sortOrder string) ([]entities.LetterOutgoing, int64, error) { db := DBFromContext(ctx, r.db) query := db.WithContext(ctx).Model(&entities.LetterOutgoing{}).Where("deleted_at IS NULL") diff --git a/internal/repository/letter_repository.go b/internal/repository/letter_repository.go index 03f3177..64e1ca7 100644 --- a/internal/repository/letter_repository.go +++ b/internal/repository/letter_repository.go @@ -242,6 +242,42 @@ func (r *LetterIncomingRepository) List(ctx context.Context, filter ListIncoming return list, total, nil } +func (r *LetterIncomingRepository) ListAll(ctx context.Context, filter ListIncomingLettersFilter, limit, offset int) ([]entities.LetterIncoming, int64, error) { + db := DBFromContext(ctx, r.db) + query := db.WithContext(ctx).Model(&entities.LetterIncoming{}).Where("deleted_at IS NULL") + + // Apply filters (same as ListAll) + if len(filter.PriorityIDs) > 0 { + query = query.Where("letters_incoming.priority_id IN ?", filter.PriorityIDs) + } + + if filter.Status != nil { + query = query.Where("letters_incoming.status = ?", *filter.Status) + } + + if filter.Query != nil { + q := "%" + *filter.Query + "%" + query = query.Where("letters_incoming.subject ILIKE ? OR letters_incoming.reference_number ILIKE ? OR letters_incoming.letter_number ILIKE ?", q, q, q) + } + + // Get total count + var total int64 + if err := query.Count(&total).Error; err != nil { + return nil, 0, err + } + + // Get paginated data with preloaded relations + var list []entities.LetterIncoming + if err := query. + Limit(limit). + Offset(offset). + Find(&list).Error; err != nil { + return nil, 0, err + } + + return list, total, nil +} + func (r *LetterIncomingRepository) Search(ctx context.Context, filters map[string]interface{}, limit, offset int, sortBy, sortOrder string) ([]entities.LetterIncoming, int64, error) { db := DBFromContext(ctx, r.db) query := db.WithContext(ctx).Model(&entities.LetterIncoming{}).Where("deleted_at IS NULL")