918 lines
33 KiB
Go
918 lines
33 KiB
Go
package repository
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"eslogad-be/internal/entities"
|
|
|
|
"github.com/google/uuid"
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
type LetterIncomingRepository struct{ db *gorm.DB }
|
|
|
|
func NewLetterIncomingRepository(db *gorm.DB) *LetterIncomingRepository {
|
|
return &LetterIncomingRepository{db: db}
|
|
}
|
|
|
|
func (r *LetterIncomingRepository) Create(ctx context.Context, e *entities.LetterIncoming) error {
|
|
db := DBFromContext(ctx, r.db)
|
|
return db.WithContext(ctx).Create(e).Error
|
|
}
|
|
func (r *LetterIncomingRepository) Get(ctx context.Context, id uuid.UUID) (*entities.LetterIncoming, error) {
|
|
db := DBFromContext(ctx, r.db)
|
|
var e entities.LetterIncoming
|
|
if err := db.WithContext(ctx).First(&e, "id = ?", id).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
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
|
|
}
|
|
|
|
func (r *LetterIncomingRepository) SoftDelete(ctx context.Context, id uuid.UUID) error {
|
|
db := DBFromContext(ctx, r.db)
|
|
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)
|
|
now := time.Now()
|
|
result := db.WithContext(ctx).
|
|
Model(&entities.LetterIncoming{}).
|
|
Where("id IN ? AND deleted_at IS NULL", letterIDs).
|
|
Updates(map[string]interface{}{
|
|
"is_archived": true,
|
|
"archived_at": now,
|
|
})
|
|
return result.RowsAffected, result.Error
|
|
}
|
|
|
|
func (r *LetterIncomingRepository) Archive(ctx context.Context, letterID uuid.UUID) error {
|
|
db := DBFromContext(ctx, r.db)
|
|
now := time.Now()
|
|
return db.WithContext(ctx).
|
|
Model(&entities.LetterIncoming{}).
|
|
Where("id = ? AND deleted_at IS NULL", letterID).
|
|
Updates(map[string]interface{}{
|
|
"is_archived": true,
|
|
"archived_at": now,
|
|
}).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
|
|
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
|
|
}
|
|
|
|
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")
|
|
}
|
|
}
|
|
|
|
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 {
|
|
query = query.Where("lidd.id IS NOT NULL AND lidd.status != 'pending'")
|
|
} else {
|
|
query = query.Where("lidd.id IS NULL OR lidd.status = 'pending'")
|
|
}
|
|
}
|
|
|
|
if len(filter.PriorityIDs) > 0 {
|
|
query = query.Where("letters_incoming.priority_id IN ?", filter.PriorityIDs)
|
|
}
|
|
|
|
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)
|
|
}
|
|
|
|
if filter.Query != nil {
|
|
q := "%" + *filter.Query + "%"
|
|
query = query.Where("letters_incoming.subject ILIKE ? OR letters_incoming.reference_number ILIKE ?", q, q)
|
|
}
|
|
|
|
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
|
|
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.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
|
|
}
|
|
|
|
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")
|
|
|
|
joinedRecipients := false
|
|
needsGroupBy := false
|
|
|
|
// Apply search filters
|
|
if q, ok := filters["query"]; ok && q != "" {
|
|
searchTerm := "%" + q.(string) + "%"
|
|
query = query.Where("subject ILIKE ? OR reference_number ILIKE ? OR letter_number ILIKE ? OR description ILIKE ? OR sender_name ILIKE ?", searchTerm, searchTerm, searchTerm, searchTerm, searchTerm)
|
|
}
|
|
|
|
if letterNumber, ok := filters["letter_number"]; ok && letterNumber != "" {
|
|
query = query.Where("letter_number ILIKE ?", "%"+letterNumber.(string)+"%")
|
|
}
|
|
|
|
if subject, ok := filters["subject"]; ok && subject != "" {
|
|
query = query.Where("subject ILIKE ?", "%"+subject.(string)+"%")
|
|
}
|
|
|
|
if status, ok := filters["status"]; ok && status != "" {
|
|
query = query.Where("status = ?", status)
|
|
}
|
|
|
|
if priorityID, ok := filters["priority_id"]; ok {
|
|
query = query.Where("priority_id = ?", priorityID)
|
|
}
|
|
|
|
if institutionID, ok := filters["sender_institution_id"]; ok {
|
|
query = query.Where("sender_institution_id = ?", institutionID)
|
|
}
|
|
|
|
if createdBy, ok := filters["created_by"]; ok {
|
|
query = query.Where("created_by = ?", createdBy)
|
|
}
|
|
|
|
if dateFrom, ok := filters["date_from"]; ok {
|
|
query = query.Where("received_date >= ?", dateFrom)
|
|
}
|
|
|
|
if dateTo, ok := filters["date_to"]; ok {
|
|
query = query.Where("received_date <= ?", dateTo)
|
|
}
|
|
|
|
// Apply user context filters if present
|
|
if userContext, ok := filters["user_context"]; ok {
|
|
if ctx, ok := userContext.(map[string]interface{}); ok {
|
|
if userID, ok := ctx["user_id"]; ok {
|
|
// User can see letters where they are recipients
|
|
query = query.Joins("JOIN letter_incoming_recipients ON letter_incoming_recipients.letter_id = letters_incoming.id").
|
|
Where("letter_incoming_recipients.recipient_user_id = ?", userID)
|
|
joinedRecipients = true
|
|
needsGroupBy = true
|
|
}
|
|
if departmentID, ok := ctx["department_id"]; ok {
|
|
// Also include letters for user's department
|
|
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_department_id = ?", departmentID)
|
|
}
|
|
}
|
|
}
|
|
|
|
// Count total results
|
|
var total int64
|
|
if needsGroupBy {
|
|
// For grouped queries, count distinct letter IDs
|
|
if err := db.WithContext(ctx).Model(&entities.LetterIncoming{}).
|
|
Joins("JOIN letter_incoming_recipients ON letter_incoming_recipients.letter_id = letters_incoming.id").
|
|
Where("letters_incoming.deleted_at IS NULL").
|
|
Distinct("letters_incoming.id").
|
|
Count(&total).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
} else {
|
|
if err := query.Count(&total).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
}
|
|
|
|
// Apply sorting
|
|
if sortBy == "" {
|
|
sortBy = "created_at"
|
|
}
|
|
if sortOrder == "" {
|
|
sortOrder = "desc"
|
|
}
|
|
|
|
validSortFields := map[string]bool{
|
|
"letter_number": true,
|
|
"subject": true,
|
|
"received_date": true,
|
|
"status": true,
|
|
"created_at": true,
|
|
"updated_at": true,
|
|
}
|
|
|
|
if !validSortFields[sortBy] {
|
|
sortBy = "created_at"
|
|
}
|
|
|
|
if sortOrder != "asc" && sortOrder != "desc" {
|
|
sortOrder = "desc"
|
|
}
|
|
|
|
orderBy := "letters_incoming." + sortBy + " " + sortOrder
|
|
|
|
// Apply grouping if necessary
|
|
if needsGroupBy {
|
|
query = query.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")
|
|
}
|
|
|
|
// Execute query
|
|
var letters []entities.LetterIncoming
|
|
if err := query.
|
|
Order(orderBy).
|
|
Limit(limit).
|
|
Offset(offset).
|
|
Find(&letters).Error; err != nil {
|
|
return nil, 0, err
|
|
}
|
|
|
|
return letters, total, nil
|
|
}
|
|
|
|
type LetterIncomingAttachmentRepository struct{ db *gorm.DB }
|
|
|
|
func NewLetterIncomingAttachmentRepository(db *gorm.DB) *LetterIncomingAttachmentRepository {
|
|
return &LetterIncomingAttachmentRepository{db: db}
|
|
}
|
|
|
|
func (r *LetterIncomingAttachmentRepository) CreateBulk(ctx context.Context, list []entities.LetterIncomingAttachment) error {
|
|
db := DBFromContext(ctx, r.db)
|
|
return db.WithContext(ctx).Create(&list).Error
|
|
}
|
|
func (r *LetterIncomingAttachmentRepository) ListByLetter(ctx context.Context, letterID uuid.UUID) ([]entities.LetterIncomingAttachment, error) {
|
|
db := DBFromContext(ctx, r.db)
|
|
var list []entities.LetterIncomingAttachment
|
|
if err := db.WithContext(ctx).Where("letter_id = ?", letterID).Order("uploaded_at ASC").Find(&list).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
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 {
|
|
return &LetterIncomingActivityLogRepository{db: db}
|
|
}
|
|
|
|
func (r *LetterIncomingActivityLogRepository) Create(ctx context.Context, e *entities.LetterIncomingActivityLog) error {
|
|
db := DBFromContext(ctx, r.db)
|
|
return db.WithContext(ctx).Create(e).Error
|
|
}
|
|
|
|
func (r *LetterIncomingActivityLogRepository) ListByLetter(ctx context.Context, letterID uuid.UUID) ([]entities.LetterIncomingActivityLog, error) {
|
|
db := DBFromContext(ctx, r.db)
|
|
var list []entities.LetterIncomingActivityLog
|
|
if err := db.WithContext(ctx).Where("letter_id = ?", letterID).Order("occurred_at ASC").Find(&list).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return list, nil
|
|
}
|
|
|
|
type LetterIncomingDispositionRepository struct{ db *gorm.DB }
|
|
|
|
func NewLetterIncomingDispositionRepository(db *gorm.DB) *LetterIncomingDispositionRepository {
|
|
return &LetterIncomingDispositionRepository{db: db}
|
|
}
|
|
func (r *LetterIncomingDispositionRepository) Create(ctx context.Context, e *entities.LetterIncomingDisposition) error {
|
|
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
|
|
if err := db.WithContext(ctx).
|
|
Where("letter_id = ?", letterID).
|
|
Preload("Department").
|
|
Preload("Departments.Department").
|
|
Preload("ActionSelections.Action").
|
|
Preload("DispositionNotes.User").
|
|
Order("created_at ASC").
|
|
Find(&list).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return list, nil
|
|
}
|
|
|
|
func (r *LetterIncomingDispositionRepository) ListByLetterIDs(ctx context.Context, letterIDs []uuid.UUID) (map[uuid.UUID][]entities.LetterIncomingDisposition, error) {
|
|
if len(letterIDs) == 0 {
|
|
return make(map[uuid.UUID][]entities.LetterIncomingDisposition), nil
|
|
}
|
|
|
|
db := DBFromContext(ctx, r.db)
|
|
var dispositions []entities.LetterIncomingDisposition
|
|
if err := db.WithContext(ctx).Where("letter_id IN ?", letterIDs).
|
|
Preload("Department").
|
|
Preload("Departments.Department").
|
|
Preload("ActionSelections.Action").
|
|
Preload("DispositionNotes.User").
|
|
Order("created_at ASC").
|
|
Find(&dispositions).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Group by letter ID
|
|
result := make(map[uuid.UUID][]entities.LetterIncomingDisposition)
|
|
for i := range dispositions { // Gunakan index, bukan value
|
|
letterID := dispositions[i].LetterID
|
|
result[letterID] = append(result[letterID], dispositions[i])
|
|
}
|
|
|
|
return result, 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
|
|
if err := db.WithContext(ctx).Where("letter_incoming_disposition_id = ?", dispositionID).Order("created_at ASC").Find(&list).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return list, nil
|
|
}
|
|
|
|
func (r *LetterIncomingDispositionDepartmentRepository) ListByDispositions(ctx context.Context, dispositionIDs []uuid.UUID) ([]entities.LetterIncomingDispositionDepartment, error) {
|
|
db := DBFromContext(ctx, r.db)
|
|
var list []entities.LetterIncomingDispositionDepartment
|
|
if len(dispositionIDs) == 0 {
|
|
return list, nil
|
|
}
|
|
if err := db.WithContext(ctx).Where("letter_incoming_disposition_id IN ?", dispositionIDs).Order("letter_incoming_disposition_id, created_at ASC").Find(&list).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return list, nil
|
|
}
|
|
|
|
type DispositionNoteRepository struct{ db *gorm.DB }
|
|
|
|
func NewDispositionNoteRepository(db *gorm.DB) *DispositionNoteRepository {
|
|
return &DispositionNoteRepository{db: db}
|
|
}
|
|
func (r *DispositionNoteRepository) Create(ctx context.Context, e *entities.DispositionNote) error {
|
|
db := DBFromContext(ctx, r.db)
|
|
return db.WithContext(ctx).Create(e).Error
|
|
}
|
|
|
|
func (r *DispositionNoteRepository) ListByDisposition(ctx context.Context, dispositionID uuid.UUID) ([]entities.DispositionNote, error) {
|
|
db := DBFromContext(ctx, r.db)
|
|
var list []entities.DispositionNote
|
|
if err := db.WithContext(ctx).Where("disposition_id = ?", dispositionID).Order("created_at ASC").Find(&list).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return list, nil
|
|
}
|
|
|
|
func (r *DispositionNoteRepository) ListByDispositions(ctx context.Context, dispositionIDs []uuid.UUID) ([]entities.DispositionNote, error) {
|
|
db := DBFromContext(ctx, r.db)
|
|
var list []entities.DispositionNote
|
|
if len(dispositionIDs) == 0 {
|
|
return list, nil
|
|
}
|
|
if err := db.WithContext(ctx).Where("disposition_id IN ?", dispositionIDs).Order("disposition_id, created_at ASC").Find(&list).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return list, nil
|
|
}
|
|
|
|
type LetterDispositionActionSelectionRepository struct{ db *gorm.DB }
|
|
|
|
func NewLetterDispositionActionSelectionRepository(db *gorm.DB) *LetterDispositionActionSelectionRepository {
|
|
return &LetterDispositionActionSelectionRepository{db: db}
|
|
}
|
|
func (r *LetterDispositionActionSelectionRepository) CreateBulk(ctx context.Context, list []entities.LetterDispositionActionSelection) error {
|
|
db := DBFromContext(ctx, r.db)
|
|
return db.WithContext(ctx).Create(&list).Error
|
|
}
|
|
func (r *LetterDispositionActionSelectionRepository) ListByDisposition(ctx context.Context, dispositionID uuid.UUID) ([]entities.LetterDispositionActionSelection, error) {
|
|
db := DBFromContext(ctx, r.db)
|
|
var list []entities.LetterDispositionActionSelection
|
|
if err := db.WithContext(ctx).Where("disposition_id = ?", dispositionID).Order("created_at ASC").Find(&list).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return list, nil
|
|
}
|
|
|
|
func (r *LetterDispositionActionSelectionRepository) ListByDispositions(ctx context.Context, dispositionIDs []uuid.UUID) ([]entities.LetterDispositionActionSelection, error) {
|
|
db := DBFromContext(ctx, r.db)
|
|
var list []entities.LetterDispositionActionSelection
|
|
if len(dispositionIDs) == 0 {
|
|
return list, nil
|
|
}
|
|
if err := db.WithContext(ctx).Where("disposition_id IN ?", dispositionIDs).Order("disposition_id, created_at ASC").Find(&list).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return list, nil
|
|
}
|
|
|
|
type LetterDiscussionRepository struct{ db *gorm.DB }
|
|
|
|
func NewLetterDiscussionRepository(db *gorm.DB) *LetterDiscussionRepository {
|
|
return &LetterDiscussionRepository{db: db}
|
|
}
|
|
func (r *LetterDiscussionRepository) Create(ctx context.Context, e *entities.LetterDiscussion) error {
|
|
db := DBFromContext(ctx, r.db)
|
|
return db.WithContext(ctx).Create(e).Error
|
|
}
|
|
func (r *LetterDiscussionRepository) Get(ctx context.Context, id uuid.UUID) (*entities.LetterDiscussion, error) {
|
|
db := DBFromContext(ctx, r.db)
|
|
var e entities.LetterDiscussion
|
|
if err := db.WithContext(ctx).First(&e, "id = ?", id).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return &e, nil
|
|
}
|
|
func (r *LetterDiscussionRepository) Update(ctx context.Context, e *entities.LetterDiscussion) error {
|
|
db := DBFromContext(ctx, r.db)
|
|
// ensure edited_at is set when updating
|
|
if e.EditedAt == nil {
|
|
now := time.Now()
|
|
e.EditedAt = &now
|
|
}
|
|
return db.WithContext(ctx).Model(&entities.LetterDiscussion{}).
|
|
Where("id = ?", e.ID).
|
|
Updates(map[string]interface{}{"message": e.Message, "mentions": e.Mentions, "edited_at": e.EditedAt}).Error
|
|
}
|
|
|
|
func (r *LetterDiscussionRepository) ListByLetter(ctx context.Context, letterID uuid.UUID) ([]entities.LetterDiscussion, error) {
|
|
db := DBFromContext(ctx, r.db)
|
|
var list []entities.LetterDiscussion
|
|
if err := db.WithContext(ctx).
|
|
Where("letter_id = ?", letterID).
|
|
Preload("User.Profile").
|
|
Order("created_at ASC").
|
|
Find(&list).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return list, nil
|
|
}
|
|
|
|
func (r *LetterDiscussionRepository) GetUsersByIDs(ctx context.Context, userIDs []uuid.UUID) ([]entities.User, error) {
|
|
if len(userIDs) == 0 {
|
|
return []entities.User{}, nil
|
|
}
|
|
|
|
db := DBFromContext(ctx, r.db)
|
|
var users []entities.User
|
|
if err := db.WithContext(ctx).
|
|
Where("id IN ?", userIDs).
|
|
Preload("Profile").
|
|
Find(&users).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
return users, nil
|
|
}
|
|
|
|
// recipients
|
|
|
|
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
|
|
if err := db.WithContext(ctx).
|
|
Model(&entities.LetterIncomingRecipient{}).
|
|
Where("recipient_department_id = ?", departmentID).
|
|
Distinct("letter_id").
|
|
Pluck("letter_id", &letterIDs).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
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
|
|
if err := db.WithContext(ctx).
|
|
Model(&entities.LetterIncomingRecipient{}).
|
|
Where("letter_id = ? AND recipient_department_id = ?", letterID, departmentID).
|
|
Count(&count).Error; err != nil {
|
|
return false, err
|
|
}
|
|
return count > 0, nil
|
|
}
|