Init All Docs
This commit is contained in:
@@ -177,14 +177,18 @@ func (r *AnalyticsRepository) GetLetterSummaryStats(ctx context.Context, startDa
|
||||
stats["total_archived"] = archivedCount
|
||||
|
||||
// Calculate average processing time
|
||||
var avgProcessingTime float64
|
||||
var avgProcessingTime *float64
|
||||
db.Table("letters_outgoing").
|
||||
Select("AVG(EXTRACT(EPOCH FROM (letters_outgoing.updated_at - letters_outgoing.created_at))/3600) as avg_hours").
|
||||
Where("letters_outgoing.status IN ('approved', 'sent', 'archived')").
|
||||
Where("letters_outgoing.deleted_at IS NULL").
|
||||
Scan(&avgProcessingTime)
|
||||
|
||||
stats["avg_processing_time"] = avgProcessingTime
|
||||
if avgProcessingTime != nil {
|
||||
stats["avg_processing_time"] = *avgProcessingTime
|
||||
} else {
|
||||
stats["avg_processing_time"] = float64(0)
|
||||
}
|
||||
|
||||
// Calculate completion rate
|
||||
var completedCount int64
|
||||
|
||||
@@ -2,7 +2,11 @@ package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"eslogad-be/internal/contract"
|
||||
"eslogad-be/internal/entities"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
@@ -26,3 +30,33 @@ func (r *AppSettingRepository) Upsert(ctx context.Context, key string, value ent
|
||||
db := DBFromContext(ctx, r.db)
|
||||
return db.WithContext(ctx).Exec("INSERT INTO app_settings(key, value) VALUES(?, ?) ON CONFLICT(key) DO UPDATE SET value = EXCLUDED.value, updated_at = CURRENT_TIMESTAMP", key, value).Error
|
||||
}
|
||||
|
||||
func (r *AppSettingRepository) GetDepartmentRecipients(ctx context.Context) ([]uuid.UUID, error) {
|
||||
setting, err := r.Get(ctx, contract.SettingIncomingLetterDepartmentRecipients)
|
||||
if err != nil {
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
return []uuid.UUID{}, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
jsonBytes, err := json.Marshal(setting.Value)
|
||||
if err != nil {
|
||||
return []uuid.UUID{}, nil
|
||||
}
|
||||
|
||||
// Try to unmarshal as the structured format first
|
||||
var recipientSetting entities.DepartmentRecipientsSetting
|
||||
if err := json.Unmarshal(jsonBytes, &recipientSetting); err == nil {
|
||||
return recipientSetting.DepartmentIDs, nil
|
||||
}
|
||||
|
||||
// If that fails, try to unmarshal as a direct array of UUIDs
|
||||
var departmentIDs []uuid.UUID
|
||||
if err := json.Unmarshal(jsonBytes, &departmentIDs); err == nil {
|
||||
return departmentIDs, nil
|
||||
}
|
||||
|
||||
// If both fail, return empty array
|
||||
return []uuid.UUID{}, nil
|
||||
}
|
||||
|
||||
@@ -19,10 +19,106 @@ func (r *DispositionRouteRepository) Create(ctx context.Context, e *entities.Dis
|
||||
db := DBFromContext(ctx, r.db)
|
||||
return db.WithContext(ctx).Create(e).Error
|
||||
}
|
||||
|
||||
// Upsert creates or updates a disposition route based on from_department_id and to_department_id
|
||||
func (r *DispositionRouteRepository) Upsert(ctx context.Context, e *entities.DispositionRoute) error {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
|
||||
// Check if route exists
|
||||
var existing entities.DispositionRoute
|
||||
err := db.WithContext(ctx).
|
||||
Where("from_department_id = ? AND to_department_id = ?", e.FromDepartmentID, e.ToDepartmentID).
|
||||
First(&existing).Error
|
||||
|
||||
if err == gorm.ErrRecordNotFound {
|
||||
// Create new route
|
||||
return db.WithContext(ctx).Create(e).Error
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Update existing route
|
||||
e.ID = existing.ID
|
||||
return db.WithContext(ctx).Model(&entities.DispositionRoute{}).
|
||||
Where("id = ?", existing.ID).
|
||||
Updates(e).Error
|
||||
}
|
||||
|
||||
// BulkUpsert performs bulk create or update for multiple routes
|
||||
func (r *DispositionRouteRepository) BulkUpsert(ctx context.Context, fromDeptID uuid.UUID, toDeptIDs []uuid.UUID, isActive bool, allowedActions entities.JSONB) (created int, updated int, err error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
|
||||
// Start transaction
|
||||
tx := db.WithContext(ctx).Begin()
|
||||
defer func() {
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
}
|
||||
}()
|
||||
|
||||
// Get existing routes for this from_department_id
|
||||
var existingRoutes []entities.DispositionRoute
|
||||
if err = tx.Where("from_department_id = ?", fromDeptID).Find(&existingRoutes).Error; err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
// Create map of existing routes
|
||||
existingMap := make(map[uuid.UUID]entities.DispositionRoute)
|
||||
for _, route := range existingRoutes {
|
||||
existingMap[route.ToDepartmentID] = route
|
||||
}
|
||||
|
||||
// Process each to_department_id
|
||||
for _, toDeptID := range toDeptIDs {
|
||||
route := entities.DispositionRoute{
|
||||
FromDepartmentID: fromDeptID,
|
||||
ToDepartmentID: toDeptID,
|
||||
IsActive: isActive,
|
||||
AllowedActions: allowedActions,
|
||||
}
|
||||
|
||||
if existing, exists := existingMap[toDeptID]; exists {
|
||||
// Update existing route
|
||||
route.ID = existing.ID
|
||||
if err = tx.Model(&entities.DispositionRoute{}).
|
||||
Where("id = ?", existing.ID).
|
||||
Updates(&route).Error; err != nil {
|
||||
return created, updated, err
|
||||
}
|
||||
updated++
|
||||
// Remove from map to track which routes to delete
|
||||
delete(existingMap, toDeptID)
|
||||
} else {
|
||||
// Create new route
|
||||
if err = tx.Create(&route).Error; err != nil {
|
||||
return created, updated, err
|
||||
}
|
||||
created++
|
||||
}
|
||||
}
|
||||
|
||||
// Optionally deactivate routes that are no longer in the list
|
||||
// (routes that exist in DB but not in the new list)
|
||||
for _, oldRoute := range existingMap {
|
||||
if err = tx.Model(&entities.DispositionRoute{}).
|
||||
Where("id = ?", oldRoute.ID).
|
||||
Update("is_active", false).Error; err != nil {
|
||||
return created, updated, err
|
||||
}
|
||||
}
|
||||
|
||||
// Commit transaction
|
||||
if err = tx.Commit().Error; err != nil {
|
||||
return 0, 0, err
|
||||
}
|
||||
|
||||
return created, updated, nil
|
||||
}
|
||||
func (r *DispositionRouteRepository) Update(ctx context.Context, e *entities.DispositionRoute) error {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
return db.WithContext(ctx).Model(&entities.DispositionRoute{}).Where("id = ?", e.ID).Updates(e).Error
|
||||
}
|
||||
|
||||
func (r *DispositionRouteRepository) Get(ctx context.Context, id uuid.UUID) (*entities.DispositionRoute, error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
var e entities.DispositionRoute
|
||||
@@ -46,7 +142,71 @@ func (r *DispositionRouteRepository) ListByFromDept(ctx context.Context, fromDep
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func (r *DispositionRouteRepository) IsEligibleForDisposition(ctx context.Context, fromDept uuid.UUID) (bool, error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
var list []entities.DispositionRoute
|
||||
if err := db.WithContext(ctx).Where("from_department_id = ?", fromDept).Find(&list).Error; err != nil {
|
||||
return false, err
|
||||
}
|
||||
return len(list) > 0, nil
|
||||
}
|
||||
|
||||
func (r *DispositionRouteRepository) SetActive(ctx context.Context, id uuid.UUID, isActive bool) error {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
return db.WithContext(ctx).Model(&entities.DispositionRoute{}).Where("id = ?", id).Update("is_active", isActive).Error
|
||||
}
|
||||
|
||||
// ListAllGrouped returns all disposition routes grouped by from_department_id
|
||||
func (r *DispositionRouteRepository) ListAllGrouped(ctx context.Context) (map[uuid.UUID][]uuid.UUID, error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
var routes []entities.DispositionRoute
|
||||
|
||||
if err := db.WithContext(ctx).
|
||||
Where("is_active = ?", true).
|
||||
Order("from_department_id, to_department_id").
|
||||
Find(&routes).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Group by from_department_id
|
||||
grouped := make(map[uuid.UUID][]uuid.UUID)
|
||||
for _, route := range routes {
|
||||
grouped[route.FromDepartmentID] = append(grouped[route.FromDepartmentID], route.ToDepartmentID)
|
||||
}
|
||||
|
||||
return grouped, nil
|
||||
}
|
||||
|
||||
// ListAllGroupedWithDepartments returns all disposition routes grouped by from_department_id with department details
|
||||
func (r *DispositionRouteRepository) ListAllGroupedWithDepartments(ctx context.Context) ([]entities.DispositionRoute, error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
var routes []entities.DispositionRoute
|
||||
|
||||
if err := db.WithContext(ctx).
|
||||
Preload("FromDepartment").
|
||||
Preload("ToDepartment").
|
||||
Where("is_active = ?", true).
|
||||
Order("from_department_id, to_department_id").
|
||||
Find(&routes).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return routes, nil
|
||||
}
|
||||
|
||||
// ListAll returns all disposition routes with department details
|
||||
func (r *DispositionRouteRepository) ListAll(ctx context.Context) ([]entities.DispositionRoute, error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
var routes []entities.DispositionRoute
|
||||
|
||||
if err := db.WithContext(ctx).
|
||||
Preload("FromDepartment").
|
||||
Preload("ToDepartment").
|
||||
Where("is_active = ?", true).
|
||||
Order("from_department_id, to_department_id").
|
||||
Find(&routes).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return routes, nil
|
||||
}
|
||||
|
||||
@@ -51,6 +51,15 @@ func (r *LetterOutgoingRepository) SoftDelete(ctx context.Context, id uuid.UUID)
|
||||
return db.WithContext(ctx).Model(&entities.LetterOutgoing{}).Where("id = ? AND deleted_at IS NULL", id).Update("deleted_at", now).Error
|
||||
}
|
||||
|
||||
func (r *LetterOutgoingRepository) BulkArchive(ctx context.Context, letterIDs []uuid.UUID) (int64, error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
result := db.WithContext(ctx).
|
||||
Model(&entities.LetterOutgoing{}).
|
||||
Where("id IN ? AND deleted_at IS NULL", letterIDs).
|
||||
Update("status", "archived")
|
||||
return result.RowsAffected, result.Error
|
||||
}
|
||||
|
||||
func (r *LetterOutgoingRepository) GetWithRelations(ctx context.Context, id uuid.UUID, relations []string) (*entities.LetterOutgoing, error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
query := db.WithContext(ctx).Where("id = ? AND deleted_at IS NULL", id)
|
||||
@@ -83,12 +92,22 @@ type ListOutgoingLettersFilter struct {
|
||||
PriorityID *uuid.UUID
|
||||
SortBy *string
|
||||
SortOrder *string
|
||||
IsArchived *bool
|
||||
}
|
||||
|
||||
func (r *LetterOutgoingRepository) List(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 is_archived filter
|
||||
if filter.IsArchived != nil {
|
||||
if *filter.IsArchived {
|
||||
query = query.Where("status = 'archived'")
|
||||
} else {
|
||||
query = query.Where("status != 'archived'")
|
||||
}
|
||||
}
|
||||
|
||||
if filter.Status != nil {
|
||||
query = query.Where("status = ?", *filter.Status)
|
||||
}
|
||||
@@ -207,6 +226,27 @@ func (r *LetterOutgoingAttachmentRepository) Delete(ctx context.Context, id uuid
|
||||
return db.WithContext(ctx).Where("id = ?", id).Delete(&entities.LetterOutgoingAttachment{}).Error
|
||||
}
|
||||
|
||||
// ListByLetterIDs fetches attachments for multiple letters in a single query
|
||||
func (r *LetterOutgoingAttachmentRepository) ListByLetterIDs(ctx context.Context, letterIDs []uuid.UUID) (map[uuid.UUID][]entities.LetterOutgoingAttachment, error) {
|
||||
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
|
||||
}
|
||||
|
||||
type LetterOutgoingRecipientRepository struct{ db *gorm.DB }
|
||||
|
||||
func NewLetterOutgoingRecipientRepository(db *gorm.DB) *LetterOutgoingRecipientRepository {
|
||||
@@ -226,6 +266,27 @@ func (r *LetterOutgoingRecipientRepository) CreateBulk(ctx context.Context, list
|
||||
return db.WithContext(ctx).Create(&list).Error
|
||||
}
|
||||
|
||||
func (r *LetterOutgoingRecipientRepository) CountUnreadByUser(ctx context.Context, userID uuid.UUID) (int, error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
var count int64
|
||||
if err := db.WithContext(ctx).
|
||||
Model(&entities.LetterOutgoingRecipient{}).
|
||||
Where("user_id = ? AND read_at IS NULL", userID).
|
||||
Count(&count).Error; err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int(count), nil
|
||||
}
|
||||
|
||||
func (r *LetterOutgoingRecipientRepository) MarkAsRead(ctx context.Context, letterID, userID uuid.UUID) error {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
now := time.Now()
|
||||
return db.WithContext(ctx).
|
||||
Model(&entities.LetterOutgoingRecipient{}).
|
||||
Where("letter_id = ? AND user_id = ?", letterID, userID).
|
||||
Update("read_at", now).Error
|
||||
}
|
||||
|
||||
func (r *LetterOutgoingRecipientRepository) ListByLetter(ctx context.Context, letterID uuid.UUID) ([]entities.LetterOutgoingRecipient, error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
var list []entities.LetterOutgoingRecipient
|
||||
@@ -255,6 +316,33 @@ func (r *LetterOutgoingRecipientRepository) DeleteByLetter(ctx context.Context,
|
||||
return db.WithContext(ctx).Where("letter_id = ?", letterID).Delete(&entities.LetterOutgoingRecipient{}).Error
|
||||
}
|
||||
|
||||
// ListByLetterIDs fetches recipients for multiple letters in a single query
|
||||
func (r *LetterOutgoingRecipientRepository) ListByLetterIDs(ctx context.Context, letterIDs []uuid.UUID) (map[uuid.UUID][]entities.LetterOutgoingRecipient, error) {
|
||||
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).
|
||||
Preload("User").
|
||||
Preload("User.Profile").
|
||||
Preload("Department").
|
||||
Where("letter_id IN ?", letterIDs).
|
||||
Order("is_primary DESC, created_at ASC").
|
||||
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
|
||||
}
|
||||
|
||||
type LetterOutgoingDiscussionRepository struct{ db *gorm.DB }
|
||||
|
||||
func NewLetterOutgoingDiscussionRepository(db *gorm.DB) *LetterOutgoingDiscussionRepository {
|
||||
|
||||
@@ -29,6 +29,10 @@ func (r *LetterIncomingRepository) Get(ctx context.Context, id uuid.UUID) (*enti
|
||||
return &e, nil
|
||||
}
|
||||
|
||||
func (r *LetterIncomingRepository) GetByID(ctx context.Context, id uuid.UUID) (*entities.LetterIncoming, error) {
|
||||
return r.Get(ctx, id)
|
||||
}
|
||||
|
||||
func (r *LetterIncomingRepository) Update(ctx context.Context, e *entities.LetterIncoming) error {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
return db.WithContext(ctx).Model(&entities.LetterIncoming{}).Where("id = ? AND deleted_at IS NULL", e.ID).Updates(e).Error
|
||||
@@ -39,21 +43,97 @@ func (r *LetterIncomingRepository) SoftDelete(ctx context.Context, id uuid.UUID)
|
||||
return db.WithContext(ctx).Exec("UPDATE letters_incoming SET deleted_at = CURRENT_TIMESTAMP WHERE id = ? AND deleted_at IS NULL", id).Error
|
||||
}
|
||||
|
||||
func (r *LetterIncomingRepository) BulkArchive(ctx context.Context, letterIDs []uuid.UUID) (int64, error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
// For incoming letters, we archive the recipients, not the letter itself
|
||||
// The letter status remains as is (new, in_progress, or completed)
|
||||
result := db.WithContext(ctx).
|
||||
Model(&entities.LetterIncomingRecipient{}).
|
||||
Where("letter_id IN ?", letterIDs).
|
||||
Update("is_archived", true)
|
||||
return result.RowsAffected, result.Error
|
||||
}
|
||||
|
||||
// BulkArchiveForUser archives letters for a specific user only
|
||||
func (r *LetterIncomingRepository) BulkArchiveForUser(ctx context.Context, letterIDs []uuid.UUID, userID uuid.UUID) (int64, error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
// Archive only the recipient records for the specific user
|
||||
// Note: letter_incoming_recipients uses recipient_user_id column
|
||||
result := db.WithContext(ctx).
|
||||
Model(&entities.LetterIncomingRecipient{}).
|
||||
Where("letter_id IN ? AND recipient_user_id = ?", letterIDs, userID).
|
||||
Update("is_archived", true)
|
||||
return result.RowsAffected, result.Error
|
||||
}
|
||||
|
||||
type ListIncomingLettersFilter struct {
|
||||
Status *string
|
||||
Query *string
|
||||
DepartmentID *uuid.UUID
|
||||
Status *string
|
||||
Query *string
|
||||
DepartmentID *uuid.UUID
|
||||
UserID *uuid.UUID
|
||||
IsRead *bool
|
||||
PriorityIDs []uuid.UUID
|
||||
IsDispositioned *bool
|
||||
IsArchived *bool
|
||||
}
|
||||
|
||||
func (r *LetterIncomingRepository) List(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")
|
||||
|
||||
|
||||
joinedRecipients := false
|
||||
needsGroupBy := false
|
||||
|
||||
if filter.DepartmentID != nil {
|
||||
query = query.Joins("JOIN letter_incoming_recipients ON letter_incoming_recipients.letter_id = letters_incoming.id").
|
||||
Where("letter_incoming_recipients.recipient_department_id = ?", *filter.DepartmentID)
|
||||
joinedRecipients = true
|
||||
needsGroupBy = true
|
||||
}
|
||||
|
||||
|
||||
// Apply is_read filter if UserID is provided
|
||||
if filter.UserID != nil && filter.IsRead != nil {
|
||||
if !joinedRecipients {
|
||||
query = query.Joins("JOIN letter_incoming_recipients ON letter_incoming_recipients.letter_id = letters_incoming.id")
|
||||
joinedRecipients = true
|
||||
needsGroupBy = true
|
||||
}
|
||||
query = query.Where("letter_incoming_recipients.recipient_user_id = ?", *filter.UserID)
|
||||
|
||||
if *filter.IsRead {
|
||||
query = query.Where("letter_incoming_recipients.read_at IS NOT NULL")
|
||||
} else {
|
||||
query = query.Where("letter_incoming_recipients.read_at IS NULL")
|
||||
}
|
||||
}
|
||||
|
||||
// Apply is_dispositioned filter if DepartmentID is provided
|
||||
if filter.DepartmentID != nil && filter.IsDispositioned != nil {
|
||||
query = query.Joins("LEFT JOIN letter_incoming_dispositions_department lidd ON lidd.letter_incoming_id = letters_incoming.id AND lidd.department_id = ?", *filter.DepartmentID)
|
||||
|
||||
if *filter.IsDispositioned {
|
||||
// Has been dispositioned (status is not 'pending' or record exists with non-pending status)
|
||||
query = query.Where("lidd.id IS NOT NULL AND lidd.status != 'pending'")
|
||||
} else {
|
||||
// Not yet dispositioned (no record or status is 'pending')
|
||||
query = query.Where("lidd.id IS NULL OR lidd.status = 'pending'")
|
||||
}
|
||||
}
|
||||
|
||||
// Apply priority filter
|
||||
if len(filter.PriorityIDs) > 0 {
|
||||
query = query.Where("letters_incoming.priority_id IN ?", filter.PriorityIDs)
|
||||
}
|
||||
|
||||
// Apply is_archived filter based on recipient's is_archived field
|
||||
if filter.IsArchived != nil {
|
||||
if *filter.IsArchived {
|
||||
query = query.Where("letter_incoming_recipients.is_archived = ?", true)
|
||||
} else {
|
||||
query = query.Where("letter_incoming_recipients.is_archived = ? OR letter_incoming_recipients.is_archived IS NULL", false)
|
||||
}
|
||||
}
|
||||
|
||||
if filter.Status != nil {
|
||||
query = query.Where("letters_incoming.status = ?", *filter.Status)
|
||||
}
|
||||
@@ -61,12 +141,76 @@ func (r *LetterIncomingRepository) List(ctx context.Context, filter ListIncoming
|
||||
q := "%" + *filter.Query + "%"
|
||||
query = query.Where("letters_incoming.subject ILIKE ? OR letters_incoming.reference_number ILIKE ?", q, q)
|
||||
}
|
||||
|
||||
// Use GROUP BY instead of DISTINCT to handle joins properly
|
||||
if needsGroupBy {
|
||||
query = query.Group("letters_incoming.id")
|
||||
}
|
||||
|
||||
var total int64
|
||||
if err := query.Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// For the actual data fetch, we need to select all columns
|
||||
var list []entities.LetterIncoming
|
||||
if err := query.Order("letters_incoming.created_at DESC").Limit(limit).Offset(offset).Find(&list).Error; err != nil {
|
||||
dataQuery := db.WithContext(ctx).Model(&entities.LetterIncoming{}).Where("deleted_at IS NULL")
|
||||
|
||||
if filter.DepartmentID != nil {
|
||||
dataQuery = dataQuery.Joins("JOIN letter_incoming_recipients ON letter_incoming_recipients.letter_id = letters_incoming.id").
|
||||
Where("letter_incoming_recipients.recipient_department_id = ?", *filter.DepartmentID)
|
||||
}
|
||||
|
||||
if filter.UserID != nil && filter.IsRead != nil {
|
||||
if filter.DepartmentID == nil {
|
||||
dataQuery = dataQuery.Joins("JOIN letter_incoming_recipients ON letter_incoming_recipients.letter_id = letters_incoming.id")
|
||||
}
|
||||
dataQuery = dataQuery.Where("letter_incoming_recipients.recipient_user_id = ?", *filter.UserID)
|
||||
|
||||
if *filter.IsRead {
|
||||
dataQuery = dataQuery.Where("letter_incoming_recipients.read_at IS NOT NULL")
|
||||
} else {
|
||||
dataQuery = dataQuery.Where("letter_incoming_recipients.read_at IS NULL")
|
||||
}
|
||||
}
|
||||
|
||||
if filter.DepartmentID != nil && filter.IsDispositioned != nil {
|
||||
dataQuery = dataQuery.Joins("LEFT JOIN letter_incoming_dispositions_department lidd ON lidd.letter_incoming_id = letters_incoming.id AND lidd.department_id = ?", *filter.DepartmentID)
|
||||
|
||||
if *filter.IsDispositioned {
|
||||
dataQuery = dataQuery.Where("lidd.id IS NOT NULL AND lidd.status != 'pending'")
|
||||
} else {
|
||||
dataQuery = dataQuery.Where("lidd.id IS NULL OR lidd.status = 'pending'")
|
||||
}
|
||||
}
|
||||
|
||||
if len(filter.PriorityIDs) > 0 {
|
||||
dataQuery = dataQuery.Where("letters_incoming.priority_id IN ?", filter.PriorityIDs)
|
||||
}
|
||||
|
||||
// Apply is_archived filter based on recipient's is_archived field
|
||||
if filter.IsArchived != nil {
|
||||
if *filter.IsArchived {
|
||||
dataQuery = dataQuery.Where("letter_incoming_recipients.is_archived = ?", true)
|
||||
} else {
|
||||
dataQuery = dataQuery.Where("letter_incoming_recipients.is_archived = ? OR letter_incoming_recipients.is_archived IS NULL", false)
|
||||
}
|
||||
}
|
||||
|
||||
if filter.Status != nil {
|
||||
dataQuery = dataQuery.Where("letters_incoming.status = ?", *filter.Status)
|
||||
}
|
||||
|
||||
if filter.Query != nil {
|
||||
q := "%" + *filter.Query + "%"
|
||||
dataQuery = dataQuery.Where("letters_incoming.subject ILIKE ? OR letters_incoming.reference_number ILIKE ?", q, q)
|
||||
}
|
||||
|
||||
if needsGroupBy {
|
||||
dataQuery = dataQuery.Group("letters_incoming.id, letters_incoming.letter_number, letters_incoming.reference_number, letters_incoming.subject, letters_incoming.description, letters_incoming.priority_id, letters_incoming.sender_institution_id, letters_incoming.received_date, letters_incoming.due_date, letters_incoming.status, letters_incoming.created_by, letters_incoming.created_at, letters_incoming.updated_at, letters_incoming.deleted_at")
|
||||
}
|
||||
|
||||
if err := dataQuery.Order("letters_incoming.created_at DESC").Limit(limit).Offset(offset).Find(&list).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return list, total, nil
|
||||
@@ -91,6 +235,26 @@ func (r *LetterIncomingAttachmentRepository) ListByLetter(ctx context.Context, l
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func (r *LetterIncomingAttachmentRepository) ListByLetterIDs(ctx context.Context, letterIDs []uuid.UUID) (map[uuid.UUID][]entities.LetterIncomingAttachment, error) {
|
||||
if len(letterIDs) == 0 {
|
||||
return make(map[uuid.UUID][]entities.LetterIncomingAttachment), nil
|
||||
}
|
||||
|
||||
db := DBFromContext(ctx, r.db)
|
||||
var attachments []entities.LetterIncomingAttachment
|
||||
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.LetterIncomingAttachment)
|
||||
for _, att := range attachments {
|
||||
result[att.LetterID] = append(result[att.LetterID], att)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
type LetterIncomingActivityLogRepository struct{ db *gorm.DB }
|
||||
|
||||
func NewLetterIncomingActivityLogRepository(db *gorm.DB) *LetterIncomingActivityLogRepository {
|
||||
@@ -120,6 +284,21 @@ func (r *LetterIncomingDispositionRepository) Create(ctx context.Context, e *ent
|
||||
db := DBFromContext(ctx, r.db)
|
||||
return db.WithContext(ctx).Create(e).Error
|
||||
}
|
||||
|
||||
func (r *LetterIncomingDispositionRepository) GetByID(ctx context.Context, id uuid.UUID) (*entities.LetterIncomingDisposition, error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
var e entities.LetterIncomingDisposition
|
||||
if err := db.WithContext(ctx).
|
||||
Preload("Department").
|
||||
Preload("Departments.Department").
|
||||
Preload("ActionSelections.Action").
|
||||
Preload("DispositionNotes.User").
|
||||
First(&e, "id = ?", id).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &e, nil
|
||||
}
|
||||
|
||||
func (r *LetterIncomingDispositionRepository) ListByLetter(ctx context.Context, letterID uuid.UUID) ([]entities.LetterIncomingDisposition, error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
var list []entities.LetterIncomingDisposition
|
||||
@@ -136,15 +315,149 @@ func (r *LetterIncomingDispositionRepository) ListByLetter(ctx context.Context,
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func (r *LetterIncomingDispositionRepository) GetByLetterIncomingID(ctx context.Context, letterIncomingID uuid.UUID) ([]entities.LetterIncomingDisposition, error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
var list []entities.LetterIncomingDisposition
|
||||
if err := db.WithContext(ctx).
|
||||
Where("letter_id = ?", letterIncomingID).
|
||||
Preload("Department").
|
||||
Preload("Departments.Department").
|
||||
Order("created_at ASC").
|
||||
Find(&list).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
type LetterIncomingDispositionDepartmentRepository struct{ db *gorm.DB }
|
||||
|
||||
func NewLetterIncomingDispositionDepartmentRepository(db *gorm.DB) *LetterIncomingDispositionDepartmentRepository {
|
||||
return &LetterIncomingDispositionDepartmentRepository{db: db}
|
||||
}
|
||||
|
||||
func (r *LetterIncomingDispositionDepartmentRepository) DB(ctx context.Context) *gorm.DB {
|
||||
return DBFromContext(ctx, r.db)
|
||||
}
|
||||
|
||||
func (r *LetterIncomingDispositionDepartmentRepository) Create(ctx context.Context, e *entities.LetterIncomingDispositionDepartment) error {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
return db.WithContext(ctx).Create(e).Error
|
||||
}
|
||||
|
||||
func (r *LetterIncomingDispositionDepartmentRepository) CreateBulk(ctx context.Context, list []entities.LetterIncomingDispositionDepartment) error {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
return db.WithContext(ctx).Create(&list).Error
|
||||
}
|
||||
|
||||
func (r *LetterIncomingDispositionDepartmentRepository) Update(ctx context.Context, e *entities.LetterIncomingDispositionDepartment) error {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
return db.WithContext(ctx).Save(e).Error
|
||||
}
|
||||
|
||||
func (r *LetterIncomingDispositionDepartmentRepository) GetByID(ctx context.Context, id uuid.UUID) (*entities.LetterIncomingDispositionDepartment, error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
var e entities.LetterIncomingDispositionDepartment
|
||||
if err := db.WithContext(ctx).
|
||||
Preload("Department").
|
||||
Preload("LetterIncoming").
|
||||
Preload("LetterIncomingDisposition").
|
||||
First(&e, "id = ?", id).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &e, nil
|
||||
}
|
||||
|
||||
func (r *LetterIncomingDispositionDepartmentRepository) GetByDispositionAndDepartment(ctx context.Context, letterIncomingID, departmentID uuid.UUID) (*entities.LetterIncomingDispositionDepartment, error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
var e entities.LetterIncomingDispositionDepartment
|
||||
if err := db.WithContext(ctx).
|
||||
Where("letter_incoming_id = ? AND department_id = ?", letterIncomingID, departmentID).
|
||||
Preload("Department").
|
||||
Preload("LetterIncoming").
|
||||
Preload("LetterIncomingDisposition").
|
||||
First(&e).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &e, nil
|
||||
}
|
||||
|
||||
func (r *LetterIncomingDispositionDepartmentRepository) GetByLetterAndDepartment(ctx context.Context, letterID, departmentID uuid.UUID) ([]entities.LetterIncomingDispositionDepartment, error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
var list []entities.LetterIncomingDispositionDepartment
|
||||
if err := db.WithContext(ctx).
|
||||
Where("letter_incoming_id = ? AND department_id = ?", letterID, departmentID).
|
||||
Preload("Department").
|
||||
Preload("LetterIncoming").
|
||||
Preload("LetterIncomingDisposition").
|
||||
Find(&list).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func (r *LetterIncomingDispositionDepartmentRepository) ListByDepartmentWithPagination(ctx context.Context, departmentID uuid.UUID, status *string, offset, limit int) ([]entities.LetterIncomingDispositionDepartment, int64, error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
query := db.WithContext(ctx).Where("department_id = ?", departmentID)
|
||||
|
||||
if status != nil && *status != "" {
|
||||
query = query.Where("status = ?", *status)
|
||||
}
|
||||
|
||||
var total int64
|
||||
if err := query.Model(&entities.LetterIncomingDispositionDepartment{}).Count(&total).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
var list []entities.LetterIncomingDispositionDepartment
|
||||
if err := query.
|
||||
Preload("Department").
|
||||
Preload("LetterIncoming").
|
||||
Preload("LetterIncomingDisposition.Department").
|
||||
Offset(offset).
|
||||
Limit(limit).
|
||||
Order("created_at DESC").
|
||||
Find(&list).Error; err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
return list, total, nil
|
||||
}
|
||||
|
||||
func (r *LetterIncomingDispositionDepartmentRepository) GetByLetterIncomingID(ctx context.Context, letterIncomingID uuid.UUID) ([]entities.LetterIncomingDispositionDepartment, error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
var list []entities.LetterIncomingDispositionDepartment
|
||||
if err := db.WithContext(ctx).
|
||||
Where("letter_incoming_id = ?", letterIncomingID).
|
||||
Preload("Department").
|
||||
Preload("LetterIncoming").
|
||||
Preload("LetterIncomingDisposition.Department").
|
||||
Order("created_at DESC").
|
||||
Find(&list).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func (r *LetterIncomingDispositionDepartmentRepository) UpdateStatus(ctx context.Context, id uuid.UUID, status entities.LetterIncomingDispositionDepartmentStatus, notes string, readAt, completedAt *time.Time) error {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
updates := map[string]interface{}{
|
||||
"status": status,
|
||||
}
|
||||
if readAt != nil {
|
||||
updates["read_at"] = readAt
|
||||
}
|
||||
if completedAt != nil {
|
||||
updates["completed_at"] = completedAt
|
||||
}
|
||||
|
||||
if notes != "" {
|
||||
updates["notes"] = notes
|
||||
}
|
||||
return db.WithContext(ctx).Model(&entities.LetterIncomingDispositionDepartment{}).
|
||||
Where("id = ?", id).
|
||||
Updates(updates).Error
|
||||
}
|
||||
|
||||
func (r *LetterIncomingDispositionDepartmentRepository) ListByDisposition(ctx context.Context, dispositionID uuid.UUID) ([]entities.LetterIncomingDispositionDepartment, error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
var list []entities.LetterIncomingDispositionDepartment
|
||||
@@ -292,11 +605,63 @@ type LetterIncomingRecipientRepository struct{ db *gorm.DB }
|
||||
func NewLetterIncomingRecipientRepository(db *gorm.DB) *LetterIncomingRecipientRepository {
|
||||
return &LetterIncomingRecipientRepository{db: db}
|
||||
}
|
||||
func (r *LetterIncomingRecipientRepository) DB(ctx context.Context) *gorm.DB {
|
||||
return DBFromContext(ctx, r.db)
|
||||
}
|
||||
|
||||
func (r *LetterIncomingRecipientRepository) CreateBulk(ctx context.Context, recs []entities.LetterIncomingRecipient) error {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
return db.WithContext(ctx).Create(&recs).Error
|
||||
}
|
||||
|
||||
func (r *LetterIncomingRecipientRepository) Create(ctx context.Context, recipient *entities.LetterIncomingRecipient) error {
|
||||
return r.DB(ctx).Create(recipient).Error
|
||||
}
|
||||
|
||||
func (r *LetterIncomingRecipientRepository) Update(ctx context.Context, recipient *entities.LetterIncomingRecipient) error {
|
||||
return r.DB(ctx).Save(recipient).Error
|
||||
}
|
||||
|
||||
func (r *LetterIncomingRecipientRepository) GetByID(ctx context.Context, id uuid.UUID) (*entities.LetterIncomingRecipient, error) {
|
||||
var recipient entities.LetterIncomingRecipient
|
||||
if err := r.DB(ctx).Where("id = ?", id).First(&recipient).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &recipient, nil
|
||||
}
|
||||
|
||||
func (r *LetterIncomingRecipientRepository) GetByLetterAndDepartment(ctx context.Context, letterID uuid.UUID, departmentID uuid.UUID) (*entities.LetterIncomingRecipient, error) {
|
||||
var recipient entities.LetterIncomingRecipient
|
||||
if err := r.DB(ctx).Where("letter_id = ? AND recipient_department_id = ?", letterID, departmentID).First(&recipient).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &recipient, nil
|
||||
}
|
||||
|
||||
func (r *LetterIncomingRecipientRepository) GetByLetterAndUser(ctx context.Context, letterID uuid.UUID, userID uuid.UUID) (*entities.LetterIncomingRecipient, error) {
|
||||
var recipient entities.LetterIncomingRecipient
|
||||
if err := r.DB(ctx).Where("letter_id = ? AND recipient_user_id = ?", letterID, userID).First(&recipient).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &recipient, nil
|
||||
}
|
||||
|
||||
func (r *LetterIncomingRecipientRepository) ListByLetter(ctx context.Context, letterID uuid.UUID) ([]entities.LetterIncomingRecipient, error) {
|
||||
var recipients []entities.LetterIncomingRecipient
|
||||
if err := r.DB(ctx).Where("letter_id = ?", letterID).Find(&recipients).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return recipients, nil
|
||||
}
|
||||
|
||||
func (r *LetterIncomingRecipientRepository) ListByDepartment(ctx context.Context, departmentID uuid.UUID) ([]entities.LetterIncomingRecipient, error) {
|
||||
var recipients []entities.LetterIncomingRecipient
|
||||
if err := r.DB(ctx).Where("recipient_department_id = ?", departmentID).Find(&recipients).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return recipients, nil
|
||||
}
|
||||
|
||||
func (r *LetterIncomingRecipientRepository) GetLetterIDsByDepartment(ctx context.Context, departmentID uuid.UUID) ([]uuid.UUID, error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
var letterIDs []uuid.UUID
|
||||
@@ -310,6 +675,60 @@ func (r *LetterIncomingRecipientRepository) GetLetterIDsByDepartment(ctx context
|
||||
return letterIDs, nil
|
||||
}
|
||||
|
||||
func (r *LetterIncomingRecipientRepository) CountReadByLetter(ctx context.Context, letterID uuid.UUID) (int, error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
var count int64
|
||||
if err := db.WithContext(ctx).
|
||||
Model(&entities.LetterIncomingRecipient{}).
|
||||
Where("letter_id = ? AND read_at IS NOT NULL", letterID).
|
||||
Count(&count).Error; err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int(count), nil
|
||||
}
|
||||
|
||||
func (r *LetterIncomingRecipientRepository) CountUnreadByUser(ctx context.Context, userID uuid.UUID) (int, error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
var count int64
|
||||
if err := db.WithContext(ctx).
|
||||
Model(&entities.LetterIncomingRecipient{}).
|
||||
Where("recipient_user_id = ? AND read_at IS NULL", userID).
|
||||
Count(&count).Error; err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int(count), nil
|
||||
}
|
||||
|
||||
func (r *LetterIncomingRecipientRepository) MarkAsRead(ctx context.Context, letterID, userID uuid.UUID) error {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
now := time.Now()
|
||||
return db.WithContext(ctx).
|
||||
Model(&entities.LetterIncomingRecipient{}).
|
||||
Where("letter_id = ? AND recipient_user_id = ?", letterID, userID).
|
||||
Update("read_at", now).Error
|
||||
}
|
||||
|
||||
func (r *LetterIncomingRecipientRepository) GetByLetterIDsAndUser(ctx context.Context, letterIDs []uuid.UUID, userID uuid.UUID) (map[uuid.UUID]*entities.LetterIncomingRecipient, error) {
|
||||
if len(letterIDs) == 0 {
|
||||
return make(map[uuid.UUID]*entities.LetterIncomingRecipient), nil
|
||||
}
|
||||
|
||||
db := DBFromContext(ctx, r.db)
|
||||
var recipients []entities.LetterIncomingRecipient
|
||||
if err := db.WithContext(ctx).
|
||||
Where("letter_id IN ? AND recipient_user_id = ?", letterIDs, userID).
|
||||
Find(&recipients).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make(map[uuid.UUID]*entities.LetterIncomingRecipient)
|
||||
for i := range recipients {
|
||||
result[recipients[i].LetterID] = &recipients[i]
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *LetterIncomingRecipientRepository) HasDepartmentAccess(ctx context.Context, letterID uuid.UUID, departmentID uuid.UUID) (bool, error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
var count int64
|
||||
|
||||
@@ -59,6 +59,24 @@ func (r *PriorityRepository) Get(ctx context.Context, id uuid.UUID) (*entities.P
|
||||
return &e, nil
|
||||
}
|
||||
|
||||
func (r *PriorityRepository) GetByIDs(ctx context.Context, ids []uuid.UUID) (map[uuid.UUID]*entities.Priority, error) {
|
||||
if len(ids) == 0 {
|
||||
return make(map[uuid.UUID]*entities.Priority), nil
|
||||
}
|
||||
|
||||
var priorities []entities.Priority
|
||||
if err := r.db.WithContext(ctx).Where("id IN ?", ids).Find(&priorities).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make(map[uuid.UUID]*entities.Priority)
|
||||
for i := range priorities {
|
||||
result[priorities[i].ID] = &priorities[i]
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
type InstitutionRepository struct{ db *gorm.DB }
|
||||
|
||||
func NewInstitutionRepository(db *gorm.DB) *InstitutionRepository {
|
||||
@@ -100,6 +118,24 @@ func (r *InstitutionRepository) Get(ctx context.Context, id uuid.UUID) (*entitie
|
||||
return &e, nil
|
||||
}
|
||||
|
||||
func (r *InstitutionRepository) GetByIDs(ctx context.Context, ids []uuid.UUID) (map[uuid.UUID]*entities.Institution, error) {
|
||||
if len(ids) == 0 {
|
||||
return make(map[uuid.UUID]*entities.Institution), nil
|
||||
}
|
||||
|
||||
var institutions []entities.Institution
|
||||
if err := r.db.WithContext(ctx).Where("id IN ?", ids).Find(&institutions).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
result := make(map[uuid.UUID]*entities.Institution)
|
||||
for i := range institutions {
|
||||
result[institutions[i].ID] = &institutions[i]
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
type DispositionActionRepository struct{ db *gorm.DB }
|
||||
|
||||
func NewDispositionActionRepository(db *gorm.DB) *DispositionActionRepository {
|
||||
@@ -188,3 +224,12 @@ func (r *DepartmentRepository) List(ctx context.Context, search string, limit, o
|
||||
|
||||
return list, total, nil
|
||||
}
|
||||
|
||||
func (r *DepartmentRepository) GetByID(ctx context.Context, id uuid.UUID) (*entities.Department, error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
var e entities.Department
|
||||
if err := db.WithContext(ctx).First(&e, "id = ?", id).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &e, nil
|
||||
}
|
||||
|
||||
@@ -13,15 +13,14 @@ func NewUserDepartmentRepository(db *gorm.DB) *UserDepartmentRepository {
|
||||
return &UserDepartmentRepository{db: db}
|
||||
}
|
||||
|
||||
type userDepartmentRow struct {
|
||||
type UserDepartmentRow struct {
|
||||
UserID uuid.UUID `gorm:"column:user_id"`
|
||||
DepartmentID uuid.UUID `gorm:"column:department_id"`
|
||||
}
|
||||
|
||||
// ListActiveByDepartmentIDs returns active user-department memberships for given department IDs.
|
||||
func (r *UserDepartmentRepository) ListActiveByDepartmentIDs(ctx context.Context, departmentIDs []uuid.UUID) ([]userDepartmentRow, error) {
|
||||
func (r *UserDepartmentRepository) ListActiveByDepartmentIDs(ctx context.Context, departmentIDs []uuid.UUID) ([]UserDepartmentRow, error) {
|
||||
db := DBFromContext(ctx, r.db)
|
||||
rows := make([]userDepartmentRow, 0)
|
||||
rows := make([]UserDepartmentRow, 0)
|
||||
if len(departmentIDs) == 0 {
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
@@ -35,6 +35,18 @@ func (r *UserRepositoryImpl) GetByID(ctx context.Context, id uuid.UUID) (*entiti
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
// GetByIDLight retrieves user without preloading relationships - for faster auth checks
|
||||
func (r *UserRepositoryImpl) GetByIDLight(ctx context.Context, id uuid.UUID) (*entities.User, error) {
|
||||
var user entities.User
|
||||
err := r.b.WithContext(ctx).
|
||||
Where("id = ?", id).
|
||||
First(&user).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &user, nil
|
||||
}
|
||||
|
||||
func (r *UserRepositoryImpl) GetByEmail(ctx context.Context, email string) (*entities.User, error) {
|
||||
var user entities.User
|
||||
err := r.b.WithContext(ctx).
|
||||
|
||||
Reference in New Issue
Block a user