[FEAT/BE] add coloumn usage_qty and change standart ensure product

This commit is contained in:
ragilap
2026-02-18 16:01:20 +07:00
parent e0d42fe6d3
commit 3da05eea02
5 changed files with 39 additions and 125 deletions
@@ -65,9 +65,7 @@ type RecordingRepository interface {
GetTotalEggProductionWeightByProjectFlockID(ctx context.Context, projectFlockID uint) (totalWeightKg float64, err error)
GetAverageTargetMetricsByProjectFlockKandangID(ctx context.Context, projectFlockKandangID uint, includeTargets bool) (RecordingTargetAverages, error)
ResyncProjectFlockPopulationUsage(ctx context.Context, tx *gorm.DB, projectFlockKandangID uint) error
ValidateFeedProductWarehouses(ctx context.Context, ids []uint) (uint, error)
ValidateEggProductWarehouses(ctx context.Context, ids []uint) (uint, error)
ValidateDepletionProductWarehouses(ctx context.Context, ids []uint) (uint, error)
ValidateProductWarehousesByFlags(ctx context.Context, ids []uint, flags []string) (uint, error)
}
type RecordingRepositoryImpl struct {
@@ -856,36 +854,11 @@ func (r *RecordingRepositoryImpl) ResyncProjectFlockPopulationUsage(ctx context.
return nil
}
func (r *RecordingRepositoryImpl) ValidateFeedProductWarehouses(ctx context.Context, ids []uint) (uint, error) {
func (r *RecordingRepositoryImpl) ValidateProductWarehousesByFlags(ctx context.Context, ids []uint, flags []string) (uint, error) {
if len(ids) == 0 {
return 0, nil
}
var invalidIDs []uint
feedFlags := []string{"PAKAN", "OVK"}
if err := r.DB().WithContext(ctx).
Table("product_warehouses pw").
Where("pw.id IN ?", ids).
Where(`NOT EXISTS (
SELECT 1 FROM flags f
WHERE f.flagable_type = 'products'
AND f.flagable_id = pw.product_id
AND UPPER(f.name) IN ?
)`, feedFlags).
Pluck("pw.id", &invalidIDs).Error; err != nil {
return 0, err
}
if len(invalidIDs) > 0 {
return invalidIDs[0], nil
}
return 0, nil
}
func (r *RecordingRepositoryImpl) ValidateEggProductWarehouses(ctx context.Context, ids []uint) (uint, error) {
if len(ids) == 0 {
return 0, nil
}
eggFlags := []string{"TELUR-UTUH", "TELUR-PECAH", "TELUR-PUTIH", "TELUR-RETAK", "TELUR"}
var invalidIDs []uint
if err := r.DB().WithContext(ctx).
Table("product_warehouses pw").
Where("pw.id IN ?", ids).
@@ -894,31 +867,7 @@ func (r *RecordingRepositoryImpl) ValidateEggProductWarehouses(ctx context.Conte
WHERE f.flagable_type = 'products'
AND f.flagable_id = pw.product_id
AND UPPER(f.name) IN ?
)`, eggFlags).
Pluck("pw.id", &invalidIDs).Error; err != nil {
return 0, err
}
if len(invalidIDs) > 0 {
return invalidIDs[0], nil
}
return 0, nil
}
func (r *RecordingRepositoryImpl) ValidateDepletionProductWarehouses(ctx context.Context, ids []uint) (uint, error) {
if len(ids) == 0 {
return 0, nil
}
ayamFlags := []string{"AYAM-AFKIR", "AYAM-CULLING", "AYAM-MATI"}
var invalidIDs []uint
if err := r.DB().WithContext(ctx).
Table("product_warehouses pw").
Where("pw.id IN ?", ids).
Where(`NOT EXISTS (
SELECT 1 FROM flags f
WHERE f.flagable_type = 'products'
AND f.flagable_id = pw.product_id
AND UPPER(f.name) IN ?
)`, ayamFlags).
)`, flags).
Pluck("pw.id", &invalidIDs).Error; err != nil {
return 0, err
}
@@ -311,13 +311,16 @@ func (s *recordingService) CreateOne(c *fiber.Ctx, req *validation.Create) (*ent
if err := s.ensureProductWarehousesExist(c, req.Stocks, req.Depletions, req.Eggs); err != nil {
return nil, err
}
if err := s.ensureFeedProductWarehouses(ctx, req.Stocks); err != nil {
feedIDs := recordingutil.CollectWarehouseIDs(req.Stocks, func(st validation.Stock) uint { return st.ProductWarehouseId })
if err := s.ensureProductWarehousesByFlags(ctx, feedIDs, []string{"PAKAN", "OVK"}, "feed"); err != nil {
return nil, err
}
if err := s.ensureDepletionProductWarehouses(ctx, req.Depletions); err != nil {
depletionIDs := recordingutil.CollectWarehouseIDs(req.Depletions, func(d validation.Depletion) uint { return d.ProductWarehouseId })
if err := s.ensureProductWarehousesByFlags(ctx, depletionIDs, []string{"AYAM-AFKIR", "AYAM-CULLING", "AYAM-MATI"}, "depletion"); err != nil {
return nil, err
}
if err := s.ensureEggProductWarehouses(ctx, req.Eggs); err != nil {
eggIDs := recordingutil.CollectWarehouseIDs(req.Eggs, func(e validation.Egg) uint { return e.ProductWarehouseId })
if err := s.ensureProductWarehousesByFlags(ctx, eggIDs, []string{"TELUR-UTUH", "TELUR-PECAH", "TELUR-PUTIH", "TELUR-RETAK", "TELUR"}, "egg"); err != nil {
return nil, err
}
actorID, err := m.ActorIDFromContext(c)
@@ -508,7 +511,8 @@ func (s recordingService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uin
if err := s.ensureProductWarehousesExist(c, req.Stocks, nil, nil); err != nil {
return err
}
if err := s.ensureFeedProductWarehouses(ctx, req.Stocks); err != nil {
feedIDs := recordingutil.CollectWarehouseIDs(req.Stocks, func(st validation.Stock) uint { return st.ProductWarehouseId })
if err := s.ensureProductWarehousesByFlags(ctx, feedIDs, []string{"PAKAN", "OVK"}, "feed"); err != nil {
return err
}
if err := s.syncRecordingStocks(ctx, tx, recordingEntity.Id, existingStocks, req.Stocks, note, actorID); err != nil {
@@ -536,7 +540,8 @@ func (s recordingService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uin
if err := s.ensureProductWarehousesExist(c, nil, req.Depletions, nil); err != nil {
return err
}
if err := s.ensureDepletionProductWarehouses(ctx, req.Depletions); err != nil {
depletionIDs := recordingutil.CollectWarehouseIDs(req.Depletions, func(d validation.Depletion) uint { return d.ProductWarehouseId })
if err := s.ensureProductWarehousesByFlags(ctx, depletionIDs, []string{"AYAM-AFKIR", "AYAM-CULLING", "AYAM-MATI"}, "depletion"); err != nil {
return err
}
if err := s.releaseRecordingDepletions(ctx, tx, existingDepletions, note, actorID); err != nil {
@@ -607,7 +612,8 @@ func (s recordingService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uin
if err := s.ensureProductWarehousesExist(c, nil, nil, req.Eggs); err != nil {
return err
}
if err := s.ensureEggProductWarehouses(ctx, req.Eggs); err != nil {
eggIDs := recordingutil.CollectWarehouseIDs(req.Eggs, func(e validation.Egg) uint { return e.ProductWarehouseId })
if err := s.ensureProductWarehousesByFlags(ctx, eggIDs, []string{"TELUR-UTUH", "TELUR-PECAH", "TELUR-PUTIH", "TELUR-RETAK", "TELUR"}, "egg"); err != nil {
return err
}
if err := ensureRecordingEggsUnused(existingEggs); err != nil {
@@ -924,43 +930,14 @@ func (s *recordingService) ensureProductWarehousesExist(c *fiber.Ctx, stocks []v
return nil
}
func (s *recordingService) ensureEggProductWarehouses(ctx context.Context, eggs []validation.Egg) error {
if len(eggs) == 0 {
func (s *recordingService) ensureProductWarehousesByFlags(ctx context.Context, ids []uint, flags []string, label string) error {
if len(ids) == 0 {
return nil
}
ids := recordingutil.CollectWarehouseIDs(eggs, func(e validation.Egg) uint { return e.ProductWarehouseId })
if err := s.validateWarehouseIDs(ctx, ids, func(ctx context.Context, ids []uint) error {
return recordingutil.EnsureEggProductWarehouses(ctx, s.Repository, ids)
}, "egg"); err != nil {
s.Log.Errorf("Failed to validate egg product warehouses: %+v", err)
return err
}
return nil
}
func (s *recordingService) ensureDepletionProductWarehouses(ctx context.Context, depletions []validation.Depletion) error {
if len(depletions) == 0 {
return nil
}
ids := recordingutil.CollectWarehouseIDs(depletions, func(d validation.Depletion) uint { return d.ProductWarehouseId })
if err := s.validateWarehouseIDs(ctx, ids, func(ctx context.Context, ids []uint) error {
return recordingutil.EnsureDepletionProductWarehouses(ctx, s.Repository, ids)
}, "depletion"); err != nil {
s.Log.Errorf("Failed to validate depletion product warehouses: %+v", err)
return err
}
return nil
}
func (s *recordingService) ensureFeedProductWarehouses(ctx context.Context, stocks []validation.Stock) error {
if len(stocks) == 0 {
return nil
}
ids := recordingutil.CollectWarehouseIDs(stocks, func(st validation.Stock) uint { return st.ProductWarehouseId })
if err := s.validateWarehouseIDs(ctx, ids, func(ctx context.Context, ids []uint) error {
return recordingutil.EnsureFeedProductWarehouses(ctx, s.Repository, ids)
}, "feed"); err != nil {
s.Log.Errorf("Failed to validate feed product warehouses: %+v", err)
return recordingutil.EnsureProductWarehousesByFlags(ctx, s.Repository, ids, flags, label)
}, label); err != nil {
s.Log.Errorf("Failed to validate %s product warehouses: %+v", label, err)
return err
}
return nil