Files
fm_be/internal/repository/mysql/dul_repo.go
2026-07-16 22:16:45 +07:00

146 lines
3.7 KiB
Go

package mysql
import (
"context"
"errors"
"strings"
"time"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"wucher/internal/domain/dul"
filemanager "wucher/internal/domain/file_manager"
"wucher/internal/shared/pkg/uuidv7"
)
type DULRepository struct {
db *gorm.DB
}
func NewDULRepository(db *gorm.DB) *DULRepository {
return &DULRepository{db: db}
}
func (r *DULRepository) WithTransaction(ctx context.Context, fn func(repo dul.Repository) error) error {
if fn == nil {
return nil
}
return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
return fn(&DULRepository{db: tx})
})
}
func (r *DULRepository) Create(ctx context.Context, row *dul.DUL) error {
if actor := actorUserIDFromContext(ctx); len(actor) > 0 {
row.CreatedBy = actor
row.UpdatedBy = actor
}
return r.db.WithContext(ctx).Omit(clause.Associations).Create(row).Error
}
func (r *DULRepository) Update(ctx context.Context, row *dul.DUL) error {
if actor := actorUserIDFromContext(ctx); len(actor) > 0 {
row.UpdatedBy = actor
}
return r.db.WithContext(ctx).Omit(clause.Associations).Save(row).Error
}
func (r *DULRepository) Delete(ctx context.Context, id []byte) error {
updates := map[string]any{"deleted_at": time.Now().UTC()}
if actor := actorUserIDFromContext(ctx); len(actor) > 0 {
updates["deleted_by"] = actor
updates["updated_by"] = actor
}
return r.db.WithContext(ctx).Model(&dul.DUL{}).Where("id = ? AND deleted_at IS NULL", id).Updates(updates).Error
}
func (r *DULRepository) GetByID(ctx context.Context, id []byte) (*dul.DUL, error) {
var row dul.DUL
err := r.db.WithContext(ctx).
Preload("Base").
Preload("Base.BaseCategory").
Where("id = ? AND deleted_at IS NULL", id).
First(&row).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil
}
if err != nil {
return nil, err
}
_ = r.loadImages(ctx, []*dul.DUL{&row})
return &row, nil
}
func (r *DULRepository) List(ctx context.Context, filter, sort string, limit, offset int, baseIDs [][]byte) ([]dul.DUL, int64, error) {
var rows []dul.DUL
var total int64
query := r.db.WithContext(ctx).Model(&dul.DUL{}).Where("deleted_at IS NULL")
if len(baseIDs) > 0 {
query = query.Where("base_id IN ?", baseIDs)
}
if s := strings.TrimSpace(filter); s != "" {
like := "%" + s + "%"
query = query.Where("name LIKE ? OR info LIKE ?", like, like)
}
if err := query.Count(&total).Error; err != nil {
return nil, 0, err
}
if strings.TrimSpace(sort) != "" {
query = query.Order(sort)
} else {
query = query.Order("base_id ASC").Order("no ASC")
}
if limit > 0 {
query = query.Limit(limit).Offset(offset)
}
if err := query.Preload("Base").Preload("Base.BaseCategory").Find(&rows).Error; err != nil {
return nil, 0, err
}
ptrs := make([]*dul.DUL, 0, len(rows))
for i := range rows {
ptrs = append(ptrs, &rows[i])
}
_ = r.loadImages(ctx, ptrs)
return rows, total, nil
}
func (r *DULRepository) loadImages(ctx context.Context, rows []*dul.DUL) error {
if len(rows) == 0 {
return nil
}
refIDs := make([]string, 0, len(rows))
byRef := map[string]*dul.DUL{}
for _, row := range rows {
if row == nil || len(row.ID) != 16 {
continue
}
refID, _ := uuidv7.BytesToString(row.ID)
refIDs = append(refIDs, refID)
byRef[refID] = row
row.Images = nil
}
if len(refIDs) == 0 {
return nil
}
var attachments []filemanager.Attachment
if err := r.db.WithContext(ctx).
Preload("File").
Where("ref_type = ? AND ref_id IN ?", "dul", refIDs).
Order("sort_order ASC, created_at ASC").
Find(&attachments).Error; err != nil {
return err
}
for i := range attachments {
att := attachments[i]
row := byRef[att.RefID]
if row == nil {
continue
}
clone := att
row.Images = append(row.Images, &clone)
}
return nil
}