feat(BE-#270): Project flock period change to project_flock_kandangs

This commit is contained in:
ragilap
2025-11-18 12:26:54 +07:00
parent 02cc082d67
commit c2b60c1aff
15 changed files with 330 additions and 156 deletions
@@ -2,7 +2,6 @@ package repository
import (
"context"
"errors"
"fmt"
"strings"
@@ -10,17 +9,12 @@ import (
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/validations"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
const baseNameExpression = "LOWER(TRIM(regexp_replace(flock_name, '\\\\s+\\\\d+(\\\\s+\\\\d+)*$', '', 'g')))"
type ProjectflockRepository interface {
repository.BaseRepository[entity.ProjectFlock]
GetAllByBaseName(ctx context.Context, baseName string) ([]entity.ProjectFlock, error)
GetActiveByBaseName(ctx context.Context, baseName string) (*entity.ProjectFlock, error)
GetMaxPeriodByBaseName(ctx context.Context, baseName string) (int, error)
GetNextSequenceForBase(ctx context.Context, baseName string) (int, error)
GetAllWithFilters(ctx context.Context, offset, limit int, params *validation.Query) ([]entity.ProjectFlock, int64, error)
WithDefaultRelations() func(*gorm.DB) *gorm.DB
ExistsByFlockName(ctx context.Context, flockName string, excludeID *uint) (bool, error)
@@ -39,65 +33,6 @@ func NewProjectflockRepository(db *gorm.DB) ProjectflockRepository {
}
}
func (r *ProjectflockRepositoryImpl) GetAllByBaseName(ctx context.Context, baseName string) ([]entity.ProjectFlock, error) {
var records []entity.ProjectFlock
if err := r.DB().WithContext(ctx).
Unscoped().
Where(baseNameExpression+" = LOWER(?)", baseName).
Order("period ASC").
Find(&records).Error; err != nil {
return nil, err
}
return records, nil
}
func (r *ProjectflockRepositoryImpl) GetActiveByBaseName(ctx context.Context, baseName string) (*entity.ProjectFlock, error) {
var record entity.ProjectFlock
err := r.DB().WithContext(ctx).
Where(baseNameExpression+" = LOWER(?)", baseName).
Order("period DESC").
First(&record).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, err
}
if err != nil {
return nil, err
}
return &record, nil
}
func (r *ProjectflockRepositoryImpl) GetMaxPeriodByBaseName(ctx context.Context, baseName string) (int, error) {
var max int
if err := r.DB().WithContext(ctx).
Model(&entity.ProjectFlock{}).
Where(baseNameExpression+" = LOWER(?)", baseName).
Select("COALESCE(MAX(period), 0)").
Scan(&max).Error; err != nil {
return 0, err
}
return max, nil
}
func (r *ProjectflockRepositoryImpl) GetNextSequenceForBase(ctx context.Context, baseName string) (int, error) {
var payload struct {
Period int
}
if err := r.DB().WithContext(ctx).
Model(&entity.ProjectFlock{}).
Where(baseNameExpression+" = LOWER(?)", baseName).
Clauses(clause.Locking{Strength: "UPDATE"}).
Order("period DESC").
Limit(1).
Select("period").
Scan(&payload).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return 1, nil
}
return 0, err
}
return payload.Period + 1, nil
}
func (r *ProjectflockRepositoryImpl) GetAllWithFilters(ctx context.Context, offset, limit int, params *validation.Query) ([]entity.ProjectFlock, int64, error) {
return r.GetAll(ctx, offset, limit, func(db *gorm.DB) *gorm.DB {
db = r.withDefaultRelations(db)
@@ -132,7 +67,13 @@ func (r *ProjectflockRepositoryImpl) applyQueryFilters(db *gorm.DB, params *vali
db = db.Where("project_flocks.location_id = ?", params.LocationId)
}
if params.Period > 0 {
db = db.Where("project_flocks.period = ?", params.Period)
db = db.Where(`
EXISTS (
SELECT 1
FROM project_flock_kandangs pfk
WHERE pfk.project_flock_id = project_flocks.id
AND pfk.period = ?
)`, params.Period)
}
if len(params.KandangIds) > 0 {
db = db.Where(`
@@ -179,10 +120,15 @@ func (r *ProjectflockRepositoryImpl) applySearchFilters(db *gorm.DB, rawSearch s
OR LOWER(created_users.email) LIKE ?
OR LOWER(project_flocks.flock_name) LIKE ?
OR LOWER(TRIM(regexp_replace(project_flocks.flock_name, '\\s+\\d+(\\s+\\d+)*$', '', 'g'))) LIKE ?
OR LOWER(CAST(project_flocks.period AS TEXT)) LIKE ?
OR EXISTS (
SELECT 1 FROM project_flock_kandangs
WHERE project_flock_kandangs.project_flock_id = project_flocks.id
AND LOWER(CAST(project_flock_kandangs.period AS TEXT)) LIKE ?
)
OR EXISTS (
SELECT 1 FROM kandangs
WHERE kandangs.project_flock_id = project_flocks.id
JOIN project_flock_kandangs pfk ON pfk.kandang_id = kandangs.id
WHERE pfk.project_flock_id = project_flocks.id
AND LOWER(kandangs.name) LIKE ?
)
`,
@@ -236,7 +182,7 @@ func (r *ProjectflockRepositoryImpl) buildOrderExpressions(sortBy, sortOrder str
}
case "period":
return []string{
fmt.Sprintf("project_flocks.period %s", direction),
fmt.Sprintf("(SELECT COALESCE(MAX(period), 0) FROM project_flock_kandangs pfk WHERE pfk.project_flock_id = project_flocks.id) %s", direction),
fmt.Sprintf("project_flocks.id %s", direction),
}
default:
@@ -19,6 +19,7 @@ type ProjectFlockKandangRepository interface {
HasKandangsLinkedToOtherProject(ctx context.Context, kandangIDs []uint, exceptProjectID *uint) (bool, error)
FindKandangsWithRecordings(ctx context.Context, projectFlockID uint, kandangIDs []uint) ([]entity.Kandang, error)
MaxPeriodByBaseName(ctx context.Context, baseName string) (int, error)
ProjectPeriodsByProjectIDs(ctx context.Context, projectIDs []uint) (map[uint]int, error)
WithTx(tx *gorm.DB) ProjectFlockKandangRepository
IdExists(ctx context.Context, id uint) (bool, error)
DB() *gorm.DB
@@ -177,7 +178,33 @@ func (r *projectFlockKandangRepositoryImpl) MaxPeriodByBaseName(ctx context.Cont
Table("project_flock_kandangs pfk").
Joins("JOIN project_flocks pf ON pf.id = pfk.project_flock_id").
Where(flockBaseNameExpression+" = LOWER(?)", baseName).
Select("COALESCE(MAX(pf.period), 0)").
Select("COALESCE(MAX(pfk.period), 0)").
Scan(&max).Error
return max, err
}
func (r *projectFlockKandangRepositoryImpl) ProjectPeriodsByProjectIDs(ctx context.Context, projectIDs []uint) (map[uint]int, error) {
result := make(map[uint]int)
if len(projectIDs) == 0 {
return result, nil
}
type row struct {
ProjectFlockID uint
Period int
}
var rows []row
if err := r.db.WithContext(ctx).
Table("project_flock_kandangs").
Where("project_flock_id IN ?", projectIDs).
Select("project_flock_id, COALESCE(MAX(period), 0) AS period").
Group("project_flock_id").
Scan(&rows).Error; err != nil {
return nil, err
}
for _, item := range rows {
result[item.ProjectFlockID] = item.Period
}
return result, nil
}