dukcapil/internal/repository/disposition_route_repository.go
2025-09-08 12:24:37 +07:00

213 lines
6.5 KiB
Go

package repository
import (
"context"
"eslogad-be/internal/entities"
"github.com/google/uuid"
"gorm.io/gorm"
)
type DispositionRouteRepository struct{ db *gorm.DB }
func NewDispositionRouteRepository(db *gorm.DB) *DispositionRouteRepository {
return &DispositionRouteRepository{db: db}
}
func (r *DispositionRouteRepository) Create(ctx context.Context, e *entities.DispositionRoute) error {
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
if err := db.WithContext(ctx).
Preload("FromDepartment").
Preload("ToDepartment").
First(&e, "id = ?", id).Error; err != nil {
return nil, err
}
return &e, nil
}
func (r *DispositionRouteRepository) ListByFromDept(ctx context.Context, fromDept uuid.UUID) ([]entities.DispositionRoute, error) {
db := DBFromContext(ctx, r.db)
var list []entities.DispositionRoute
if err := db.WithContext(ctx).Where("from_department_id = ?", fromDept).
Preload("FromDepartment").
Preload("ToDepartment").
Order("to_department_id").Find(&list).Error; err != nil {
return nil, err
}
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
}