fix merging

This commit is contained in:
ragilap
2025-11-21 10:50:30 +07:00
parent 53b226f243
commit 3fc330d8f7
5 changed files with 151 additions and 100 deletions
@@ -37,7 +37,7 @@ type ProjectflockService interface {
GetAvailableDocQuantity(ctx *fiber.Ctx, kandangID uint) (float64, error)
DeleteOne(ctx *fiber.Ctx, id uint) error
GetProjectFlockKandangByProjectAndKandang(ctx *fiber.Ctx, projectFlockID uint, kandangID uint) (*entity.ProjectFlockKandang, float64, error)
GetFlockPeriodSummary(ctx *fiber.Ctx, locationID uint) ([]KandangPeriodSummary, error)
GetPeriodSummary(ctx *fiber.Ctx, locationID uint) ([]KandangPeriodSummary, error)
GetProjectPeriods(ctx *fiber.Ctx, projectIDs []uint) (map[uint]int, error)
Approval(ctx *fiber.Ctx, req *validation.Approve) ([]entity.ProjectFlock, error)
}
@@ -85,18 +85,6 @@ func NewProjectflockService(
}
}
func (s projectflockService) withRelations(db *gorm.DB) *gorm.DB {
return db.
Preload("CreatedUser").
Preload("Flock").
Preload("Area").
Preload("Fcr").
Preload("Location").
Preload("Kandangs").
Preload("KandangHistory").
Preload("KandangHistory.Kandang")
}
func (s projectflockService) GetAll(c *fiber.Ctx, params *validation.Query) ([]entity.ProjectFlock, int64, map[uint]*flockDTO.FlockRelationDTO, error) {
if err := s.Validate.Struct(params); err != nil {
return nil, 0, nil, err
@@ -124,9 +112,7 @@ func (s projectflockService) GetAll(c *fiber.Ctx, params *validation.Query) ([]e
ids[i] = item.Id
}
latestMap, err := s.ApprovalSvc.LatestByTargets(c.Context(), s.approvalWorkflow, ids, func(db *gorm.DB) *gorm.DB {
return s.withRelations(db)
})
latestMap, err := s.ApprovalSvc.LatestByTargets(c.Context(), s.approvalWorkflow, ids, s.Repository.WithDefaultRelations())
if err != nil {
s.Log.Warnf("Unable to load latest approvals for projectflocks: %+v", err)
} else if len(latestMap) > 0 {
@@ -170,9 +156,7 @@ func (s projectflockService) getOneEntityOnly(c *fiber.Ctx, id uint) (*entity.Pr
}
if s.ApprovalSvc != nil {
approvals, err := s.ApprovalSvc.ListByTarget(c.Context(), s.approvalWorkflow, id, func(db *gorm.DB) *gorm.DB {
return s.withRelations(db)
})
approvals, err := s.ApprovalSvc.ListByTarget(c.Context(), s.approvalWorkflow, id, s.Repository.WithDefaultRelations())
if err != nil {
s.Log.Warnf("Unable to load approvals for projectflock %d: %+v", id, err)
} else if len(approvals) > 0 {
@@ -199,9 +183,7 @@ func (s projectflockService) GetOne(c *fiber.Ctx, id uint) (*entity.ProjectFlock
}
if s.ApprovalSvc != nil {
approvals, err := s.ApprovalSvc.ListByTarget(c.Context(), s.approvalWorkflow, id, func(db *gorm.DB) *gorm.DB {
return s.withRelations(db)
})
approvals, err := s.ApprovalSvc.ListByTarget(c.Context(), s.approvalWorkflow, id, s.Repository.WithDefaultRelations())
if err != nil {
s.Log.Warnf("Unable to load approvals for projectflock %d: %+v", id, err)
} else if len(approvals) > 0 {
@@ -320,13 +302,12 @@ func (s *projectflockService) CreateOne(c *fiber.Ctx, req *validation.Create) (*
return err
}
// Compute period based on location history (max period in that location + 1),
// and store it on project_flock_kandangs only.
nextPeriod, err := s.nextLocationPeriod(c.Context(), dbTransaction, req.LocationId)
// Compute period per kandang so every kandang maintains its own cycle history.
periods, err := projectRepo.GetNextPeriodsForKandangs(c.Context(), kandangIDs)
if err != nil {
return err
}
if err := s.attachKandangs(c.Context(), dbTransaction, createBody.Id, kandangIDs, nextPeriod); err != nil {
if err := s.attachKandangs(c.Context(), dbTransaction, createBody.Id, kandangIDs, periods); err != nil {
return err
}
@@ -544,19 +525,24 @@ func (s projectflockService) UpdateOne(c *fiber.Ctx, req *validation.Update, id
}
if len(toAttach) > 0 {
var currentPeriod int
if err := dbTransaction.WithContext(c.Context()).
Table("project_flock_kandangs").
Where("project_flock_id = ?", id).
Select("COALESCE(MAX(period), 0)").
Scan(&currentPeriod).Error; err != nil {
currentPeriod, err := projectRepo.GetCurrentProjectPeriod(c.Context(), id)
if err != nil {
return err
}
if currentPeriod <= 0 {
currentPeriod = 1
periods := make(map[uint]int, len(toAttach))
if currentPeriod > 0 {
for _, kid := range toAttach {
periods[kid] = currentPeriod
}
} else {
periods, err = projectRepo.GetNextPeriodsForKandangs(c.Context(), toAttach)
if err != nil {
return err
}
}
if err := s.attachKandangs(c.Context(), dbTransaction, id, toAttach, currentPeriod); err != nil {
if err := s.attachKandangs(c.Context(), dbTransaction, id, toAttach, periods); err != nil {
return err
}
}
@@ -832,32 +818,6 @@ func (s projectflockService) GetAvailableDocQuantity(ctx *fiber.Ctx, kandangID u
return total, nil
}
// nextLocationPeriod computes the next period number for a given location
// based on the maximum period that has ever been used by any kandang in that location.
func (s projectflockService) nextLocationPeriod(ctx context.Context, tx *gorm.DB, locationID uint) (int, error) {
if locationID == 0 {
return 0, fiber.NewError(fiber.StatusBadRequest, "location_id is required to compute period")
}
db := s.Repository.DB()
if tx != nil {
db = tx
}
var maxPeriod int
if err := db.WithContext(ctx).
Table("project_flock_kandangs pfk").
Joins("JOIN kandangs k ON k.id = pfk.kandang_id").
Where("k.location_id = ?", locationID).
Select("COALESCE(MAX(pfk.period), 0)").
Scan(&maxPeriod).Error; err != nil {
s.Log.Errorf("Failed to compute max period for location %d: %+v", locationID, err)
return 0, fiber.NewError(fiber.StatusInternalServerError, "Failed to compute period for location")
}
return maxPeriod + 1, nil
}
func (s projectflockService) GetProjectPeriods(c *fiber.Ctx, projectIDs []uint) (map[uint]int, error) {
if len(projectIDs) == 0 {
return map[uint]int{}, nil
@@ -865,7 +825,7 @@ func (s projectflockService) GetProjectPeriods(c *fiber.Ctx, projectIDs []uint)
return s.pivotRepo().ProjectPeriodsByProjectIDs(c.Context(), projectIDs)
}
func (s projectflockService) GetFlockPeriodSummary(c *fiber.Ctx, locationID uint) ([]KandangPeriodSummary, error) {
func (s projectflockService) GetPeriodSummary(c *fiber.Ctx, locationID uint) ([]KandangPeriodSummary, error) {
if locationID == 0 {
return nil, fiber.NewError(fiber.StatusBadRequest, "location_id is required")
}
@@ -879,24 +839,8 @@ func (s projectflockService) GetFlockPeriodSummary(c *fiber.Ctx, locationID uint
return nil, fiber.NewError(fiber.StatusNotFound, "Location not found")
}
type kandangPeriodRow struct {
Id uint
Name string
LatestPeriod int
}
var rows []kandangPeriodRow
db := s.Repository.DB().WithContext(c.Context())
if err := db.
Table("kandangs AS k").
Select("k.id, k.name, COALESCE(MAX(pfk.period), 0) AS latest_period").
Joins("LEFT JOIN project_flock_kandangs AS pfk ON pfk.kandang_id = k.id").
Where("k.location_id = ?", locationID).
Where("k.deleted_at IS NULL").
Group("k.id, k.name").
Order("k.id ASC").
Scan(&rows).Error; err != nil {
rows, err := s.Repository.GetKandangPeriodSummaryRows(c.Context(), locationID)
if err != nil {
s.Log.Errorf("Failed to fetch kandang period summary for location %d: %+v", locationID, err)
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch kandang period summary")
}
@@ -991,7 +935,7 @@ func (s projectflockService) ensureFlockByName(ctx context.Context, actorID uint
return newFlock, nil
}
func (s projectflockService) attachKandangs(ctx context.Context, dbTransaction *gorm.DB, projectFlockID uint, kandangIDs []uint, period int) error {
func (s projectflockService) attachKandangs(ctx context.Context, dbTransaction *gorm.DB, projectFlockID uint, kandangIDs []uint, periods map[uint]int) error {
if len(kandangIDs) == 0 {
return nil
}
@@ -1026,6 +970,10 @@ func (s projectflockService) attachKandangs(ctx context.Context, dbTransaction *
records := make([]*entity.ProjectFlockKandang, 0, len(toAttach))
for _, id := range toAttach {
period := periods[id]
if period <= 0 {
period = 1
}
records = append(records, &entity.ProjectFlockKandang{
ProjectFlockId: projectFlockID,
KandangId: id,