feat(BE-281): deleting bw in recording

This commit is contained in:
ragilap
2025-12-29 09:38:49 +07:00
parent 98a34a1640
commit 411d6fe6a9
8 changed files with 110 additions and 136 deletions
@@ -39,18 +39,11 @@ type RecordingListDTO struct {
type RecordingDetailDTO struct {
RecordingListDTO
BodyWeights []RecordingBodyWeightDTO `json:"body_weights"`
Depletions []RecordingDepletionDTO `json:"depletions"`
Stocks []RecordingStockDTO `json:"stocks"`
Eggs []RecordingEggDTO `json:"eggs"`
}
type RecordingBodyWeightDTO struct {
AvgWeight float64 `json:"avg_weight"`
Qty float64 `json:"qty"`
TotalWeight float64 `json:"total_weight"`
}
type RecordingDepletionDTO struct {
ProductWarehouseId uint `json:"product_warehouse_id"`
Qty float64 `json:"qty"`
@@ -183,25 +176,12 @@ func ToRecordingDetailDTO(e entity.Recording) RecordingDetailDTO {
return RecordingDetailDTO{
RecordingListDTO: listDTO,
BodyWeights: ToRecordingBodyWeightDTOs(e.BodyWeights),
Depletions: ToRecordingDepletionDTOs(e.Depletions),
Stocks: ToRecordingStockDTOs(e.Stocks),
Eggs: eggs,
}
}
func ToRecordingBodyWeightDTOs(bodyWeights []entity.RecordingBW) []RecordingBodyWeightDTO {
result := make([]RecordingBodyWeightDTO, len(bodyWeights))
for i, bw := range bodyWeights {
result[i] = RecordingBodyWeightDTO{
AvgWeight: bw.AvgWeight,
Qty: bw.Qty,
TotalWeight: bw.TotalWeight,
}
}
return result
}
func ToRecordingDepletionDTOs(depletions []entity.RecordingDepletion) []RecordingDepletionDTO {
result := make([]RecordingDepletionDTO, len(depletions))
for i, d := range depletions {
@@ -66,7 +66,6 @@ func (r *RecordingRepositoryImpl) WithRelations(db *gorm.DB) *gorm.DB {
Preload("CreatedUser").
Preload("ProjectFlockKandang").
Preload("ProjectFlockKandang.ProjectFlock").
Preload("BodyWeights").
Preload("Depletions").
Preload("Depletions.ProductWarehouse").
Preload("Depletions.ProductWarehouse.Product").
@@ -233,12 +233,6 @@ func (s *recordingService) CreateOne(c *fiber.Ctx, req *validation.Create) (*ent
return err
}
mappedBodyWeights := recordingutil.MapBodyWeights(createdRecording.Id, req.BodyWeights)
if err := s.Repository.CreateBodyWeights(tx, mappedBodyWeights); err != nil {
s.Log.Errorf("Failed to persist body weights: %+v", err)
return err
}
mappedStocks := recordingutil.MapStocks(createdRecording.Id, req.Stocks)
if err := s.Repository.CreateStocks(tx, mappedStocks); err != nil {
s.Log.Errorf("Failed to persist stocks: %+v", err)
@@ -291,7 +285,7 @@ func (s recordingService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uin
return nil, err
}
if req.BodyWeights == nil && req.Stocks == nil && req.Depletions == nil && req.Eggs == nil {
if req.Stocks == nil && req.Depletions == nil && req.Eggs == nil {
return s.GetOne(c, id)
}
@@ -311,12 +305,11 @@ func (s recordingService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uin
}
recordingEntity = recording
hasBodyChanges := req.BodyWeights != nil
hasStockChanges := req.Stocks != nil
hasDepletionChanges := req.Depletions != nil
hasEggChanges := req.Eggs != nil
if !hasBodyChanges && !hasStockChanges && !hasDepletionChanges && !hasEggChanges {
if !hasStockChanges && !hasDepletionChanges && !hasEggChanges {
return nil
}
@@ -346,17 +339,6 @@ func (s recordingService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uin
}
}
if hasBodyChanges {
if err := s.Repository.DeleteBodyWeights(tx, recordingEntity.Id); err != nil {
s.Log.Errorf("Failed to clear body weights: %+v", err)
return err
}
if err := s.Repository.CreateBodyWeights(tx, recordingutil.MapBodyWeights(recordingEntity.Id, req.BodyWeights)); err != nil {
s.Log.Errorf("Failed to update body weights: %+v", err)
return err
}
}
if hasStockChanges {
existingStocks, err := s.Repository.ListStocks(tx, recordingEntity.Id)
if err != nil {
@@ -432,7 +414,7 @@ func (s recordingService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uin
}
}
if hasBodyChanges || hasStockChanges || hasDepletionChanges {
if hasStockChanges || hasDepletionChanges {
if err := s.computeAndUpdateMetrics(ctx, tx, recordingEntity); err != nil {
s.Log.Errorf("Failed to recompute recording metrics: %+v", err)
return err
@@ -775,7 +757,6 @@ func (s *recordingService) computeAndUpdateMetrics(ctx context.Context, tx *gorm
var prevCumDepletionQty float64
var prevCumIntake float64
var prevAvgWeight float64
if prevRecording != nil {
if prevRecording.TotalDepletionQty != nil {
prevCumDepletionQty = *prevRecording.TotalDepletionQty
@@ -783,10 +764,6 @@ func (s *recordingService) computeAndUpdateMetrics(ctx context.Context, tx *gorm
if prevRecording.CumIntake != nil {
prevCumIntake = float64(*prevRecording.CumIntake)
}
prevAvgWeight, err = s.Repository.GetAverageBodyWeight(tx, prevRecording.Id)
if err != nil {
return fmt.Errorf("getAverageBodyWeight(prev): %w", err)
}
}
totalChick, err := s.Repository.GetTotalChick(tx, recording.ProjectFlockKandangId)
@@ -794,21 +771,11 @@ func (s *recordingService) computeAndUpdateMetrics(ctx context.Context, tx *gorm
return fmt.Errorf("getTotalChick: %w", err)
}
currentAvgWeight, err := s.Repository.GetAverageBodyWeight(tx, recording.Id)
if err != nil {
return fmt.Errorf("getAverageBodyWeight(current): %w", err)
}
usageInGrams, err := s.Repository.GetFeedUsageInGrams(tx, recording.Id)
if err != nil {
return fmt.Errorf("getFeedUsageInGrams: %w", err)
}
currentAvgGrams := recordingutil.ToGrams(currentAvgWeight)
currentAvgKg := recordingutil.GramsToKg(currentAvgGrams)
prevAvgGrams := recordingutil.ToGrams(prevAvgWeight)
prevAvgKg := recordingutil.GramsToKg(prevAvgGrams)
currentDepletion := float64(totalDepletionQty)
cumDepletionQty := prevCumDepletionQty + currentDepletion
@@ -840,25 +807,10 @@ func (s *recordingService) computeAndUpdateMetrics(ctx context.Context, tx *gorm
recording.CumDepletionRate = nil
}
if currentAvgGrams > 0 && prevAvgGrams > 0 {
dailyGainKg := (currentAvgGrams - prevAvgGrams) / 1000
updates["daily_gain"] = dailyGainKg
recording.DailyGain = &dailyGainKg
} else {
dailyGainKg := 0.0
updates["daily_gain"] = dailyGainKg
recording.DailyGain = &dailyGainKg
}
if currentAvgKg > 0 && remainingChick > 0 {
avgDailyGain := (currentAvgKg - prevAvgKg) / remainingChick
updates["avg_daily_gain"] = avgDailyGain
recording.AvgDailyGain = &avgDailyGain
} else {
avgDailyGain := 0.0
updates["avg_daily_gain"] = avgDailyGain
recording.AvgDailyGain = &avgDailyGain
}
updates["daily_gain"] = gorm.Expr("NULL")
updates["avg_daily_gain"] = gorm.Expr("NULL")
recording.DailyGain = nil
recording.AvgDailyGain = nil
if usageInGrams > 0 && totalChick > 0 {
var cumIntakeValue float64
@@ -882,15 +834,8 @@ func (s *recordingService) computeAndUpdateMetrics(ctx context.Context, tx *gorm
recording.CumIntake = nil
}
if usageInGrams > 0 && currentAvgKg > 0 {
feedUsageKg := usageInGrams / 1000
fcrValue := feedUsageKg / currentAvgKg
updates["fcr_value"] = fcrValue
recording.FcrValue = &fcrValue
} else {
updates["fcr_value"] = gorm.Expr("NULL")
recording.FcrValue = nil
}
updates["fcr_value"] = gorm.Expr("NULL")
recording.FcrValue = nil
if err := s.Repository.WithTx(tx).PatchOne(ctx, recording.Id, updates, nil); err != nil {
return err
@@ -1,12 +1,6 @@
package validation
type (
BodyWeight struct {
AvgWeight float64 `json:"avg_weight" validate:"required"`
Qty float64 `json:"qty" validate:"required,gt=0"`
TotalWeight *float64 `json:"total_weight,omitempty" validate:"omitempty,gte=0"`
}
Stock struct {
ProductWarehouseId uint `json:"product_warehouse_id" validate:"required,number,min=1"`
Qty float64 `json:"qty" validate:"required,gte=0"`
@@ -27,14 +21,12 @@ type (
type Create struct {
ProjectFlockKandangId uint `json:"project_flock_kandang_id" validate:"required,number,min=1"`
BodyWeights []BodyWeight `json:"body_weights" validate:"dive"`
Stocks []Stock `json:"stocks" validate:"dive"`
Depletions []Depletion `json:"depletions" validate:"dive"`
Eggs []Egg `json:"eggs" validate:"omitempty,dive"`
}
type Update struct {
BodyWeights []BodyWeight `json:"body_weights,omitempty" validate:"omitempty,dive"`
Stocks []Stock `json:"stocks,omitempty" validate:"omitempty,dive"`
Depletions []Depletion `json:"depletions,omitempty" validate:"omitempty,dive"`
Eggs []Egg `json:"eggs,omitempty" validate:"omitempty,dive"`