mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
[FEAT/BE]Fix add new response depletions_rate
This commit is contained in:
@@ -12,7 +12,9 @@ type Recording struct {
|
||||
RecordDatetime time.Time `gorm:"column:record_datetime;not null"`
|
||||
Day *int `gorm:"column:day"`
|
||||
TotalDepletionQty *float64 `gorm:"column:total_depletion_qty"`
|
||||
TotalDepletionCumQty *float64 `gorm:"-"`
|
||||
CumDepletionRate *float64 `gorm:"column:cum_depletion_rate"`
|
||||
DepletionRate *float64 `gorm:"-"`
|
||||
CumIntake *int `gorm:"column:cum_intake"`
|
||||
FcrValue *float64 `gorm:"column:fcr_value"`
|
||||
TotalChickQty *float64 `gorm:"column:total_chick_qty"`
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -73,7 +74,9 @@ type RecordingRelationDTO struct {
|
||||
RecordDatetime time.Time `json:"record_datetime"`
|
||||
Day int `json:"day"`
|
||||
TotalDepletionQty float64 `json:"total_depletion_qty"`
|
||||
TotalDepletionCumQty float64 `json:"total_depletion_cum_qty"`
|
||||
CumDepletionRate float64 `json:"cum_depletion_rate"`
|
||||
DepletionRate float64 `json:"depletion_rate"`
|
||||
CumIntake int `json:"cum_intake"`
|
||||
FcrValue float64 `json:"fcr_value"`
|
||||
HenDay float64 `json:"hen_day"`
|
||||
@@ -230,7 +233,9 @@ func toRecordingRelationDTO(e entity.Recording) RecordingRelationDTO {
|
||||
RecordDatetime: e.RecordDatetime,
|
||||
Day: intValue(e.Day),
|
||||
TotalDepletionQty: floatValue(e.TotalDepletionQty),
|
||||
CumDepletionRate: floatValue(e.CumDepletionRate),
|
||||
TotalDepletionCumQty: floatValue(e.TotalDepletionCumQty),
|
||||
CumDepletionRate: roundFloatValue(e.CumDepletionRate, 2),
|
||||
DepletionRate: roundFloatValue(e.DepletionRate, 2),
|
||||
CumIntake: intValue(e.CumIntake),
|
||||
FcrValue: floatValue(e.FcrValue),
|
||||
HenDay: floatValue(e.HenDay),
|
||||
@@ -426,6 +431,17 @@ func floatValue(value *float64) float64 {
|
||||
return *value
|
||||
}
|
||||
|
||||
func roundFloatValue(value *float64, places int) float64 {
|
||||
if value == nil {
|
||||
return 0
|
||||
}
|
||||
if places <= 0 {
|
||||
return math.Round(*value)
|
||||
}
|
||||
factor := math.Pow(10, float64(places))
|
||||
return math.Round(*value*factor) / factor
|
||||
}
|
||||
|
||||
func intValue(value *int) int {
|
||||
if value == nil {
|
||||
return 0
|
||||
|
||||
@@ -39,6 +39,7 @@ type RecordingRepository interface {
|
||||
ExistsOnDate(ctx context.Context, projectFlockKandangId uint, recordTime time.Time) (bool, error)
|
||||
|
||||
SumRecordingDepletions(tx *gorm.DB, recordingID uint) (float64, error)
|
||||
GetCumulativeDepletionByProjectFlockKandangUntil(tx *gorm.DB, projectFlockKandangId uint, recordTime time.Time) (float64, error)
|
||||
FindPreviousRecording(tx *gorm.DB, projectFlockKandangId uint, currentDay int) (*entity.Recording, error)
|
||||
GetTotalChick(tx *gorm.DB, projectFlockKandangId uint) (int64, error)
|
||||
GetTotalChickinByProjectFlockKandang(tx *gorm.DB, projectFlockKandangId uint) (float64, error)
|
||||
@@ -314,6 +315,23 @@ func (r *RecordingRepositoryImpl) SumRecordingDepletions(tx *gorm.DB, recordingI
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *RecordingRepositoryImpl) GetCumulativeDepletionByProjectFlockKandangUntil(tx *gorm.DB, projectFlockKandangId uint, recordTime time.Time) (float64, error) {
|
||||
if projectFlockKandangId == 0 || recordTime.IsZero() {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
var total float64
|
||||
err := tx.
|
||||
Table("recording_depletions rd").
|
||||
Select("COALESCE(SUM(rd.qty),0)").
|
||||
Joins("JOIN recordings r ON r.id = rd.recording_id").
|
||||
Where("r.project_flock_kandangs_id = ?", projectFlockKandangId).
|
||||
Where("r.record_datetime <= ?", recordTime).
|
||||
Where("r.deleted_at IS NULL").
|
||||
Scan(&total).Error
|
||||
return total, err
|
||||
}
|
||||
|
||||
func (r *RecordingRepositoryImpl) FindPreviousRecording(tx *gorm.DB, projectFlockKandangId uint, currentDay int) (*entity.Recording, error) {
|
||||
if currentDay <= 1 {
|
||||
return nil, nil
|
||||
|
||||
@@ -128,6 +128,12 @@ func (s recordingService) GetAll(c *fiber.Ctx, params *validation.Query) ([]enti
|
||||
if err := s.attachProductionStandards(c.Context(), recordings); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if err := s.attachCumulativeDepletions(c.Context(), recordings); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
if err := s.attachDepletionRates(c.Context(), recordings); err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
return recordings, total, nil
|
||||
}
|
||||
|
||||
@@ -152,6 +158,12 @@ func (s recordingService) GetOne(c *fiber.Ctx, id uint) (*entity.Recording, erro
|
||||
if err := s.attachProductionStandard(c.Context(), recording); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := s.attachCumulativeDepletion(c.Context(), recording); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := s.attachDepletionRate(c.Context(), recording); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return recording, nil
|
||||
}
|
||||
|
||||
@@ -1026,12 +1038,8 @@ func (s *recordingService) computeAndUpdateMetrics(ctx context.Context, tx *gorm
|
||||
return fmt.Errorf("getPreviousRecording: %w", err)
|
||||
}
|
||||
|
||||
var prevCumDepletionQty float64
|
||||
var prevCumIntake float64
|
||||
if prevRecording != nil {
|
||||
if prevRecording.TotalDepletionQty != nil {
|
||||
prevCumDepletionQty = *prevRecording.TotalDepletionQty
|
||||
}
|
||||
if prevRecording.CumIntake != nil {
|
||||
prevCumIntake = float64(*prevRecording.CumIntake)
|
||||
}
|
||||
@@ -1063,12 +1071,16 @@ func (s *recordingService) computeAndUpdateMetrics(ctx context.Context, tx *gorm
|
||||
}
|
||||
|
||||
currentDepletion := float64(totalDepletionQty)
|
||||
cumDepletionQty := prevCumDepletionQty + currentDepletion
|
||||
cumDepletionQty, err := s.Repository.GetCumulativeDepletionByProjectFlockKandangUntil(tx, recording.ProjectFlockKandangId, recording.RecordDatetime)
|
||||
if err != nil {
|
||||
return fmt.Errorf("getCumulativeDepletionByProjectFlockKandangUntil: %w", err)
|
||||
}
|
||||
|
||||
updates := map[string]any{
|
||||
"total_depletion_qty": cumDepletionQty,
|
||||
"total_depletion_qty": currentDepletion,
|
||||
}
|
||||
recording.TotalDepletionQty = &cumDepletionQty
|
||||
recording.TotalDepletionQty = ¤tDepletion
|
||||
recording.TotalDepletionCumQty = &cumDepletionQty
|
||||
|
||||
var remainingChick float64
|
||||
if totalChick > 0 {
|
||||
@@ -1111,6 +1123,9 @@ func (s *recordingService) computeAndUpdateMetrics(ctx context.Context, tx *gorm
|
||||
recording.CumDepletionRate = nil
|
||||
}
|
||||
|
||||
depletionRate := computeDepletionRate(prevRecording, currentDepletion, totalChick)
|
||||
recording.DepletionRate = &depletionRate
|
||||
|
||||
var feedIntake float64
|
||||
if remainingChick > 0 && usageInGrams > 0 {
|
||||
feedIntake = (usageInGrams / remainingChick) * 1000
|
||||
@@ -1201,6 +1216,81 @@ func (s *recordingService) computeAndUpdateMetrics(ctx context.Context, tx *gorm
|
||||
return nil
|
||||
}
|
||||
|
||||
func computeDepletionRate(prevRecording *entity.Recording, currentDepletion float64, totalChick int64) float64 {
|
||||
base := 0.0
|
||||
if prevRecording != nil && prevRecording.TotalChickQty != nil && *prevRecording.TotalChickQty > 0 {
|
||||
base = *prevRecording.TotalChickQty
|
||||
} else if totalChick > 0 {
|
||||
// totalChick is already remaining after today's depletion; add back current to approximate previous population.
|
||||
base = float64(totalChick) + currentDepletion
|
||||
}
|
||||
if base <= 0 {
|
||||
return 0
|
||||
}
|
||||
return (currentDepletion / base) * 100
|
||||
}
|
||||
|
||||
func (s *recordingService) attachCumulativeDepletion(ctx context.Context, recording *entity.Recording) error {
|
||||
if recording == nil || recording.ProjectFlockKandangId == 0 || recording.RecordDatetime.IsZero() {
|
||||
return nil
|
||||
}
|
||||
total, err := s.Repository.GetCumulativeDepletionByProjectFlockKandangUntil(s.Repository.DB().WithContext(ctx), recording.ProjectFlockKandangId, recording.RecordDatetime)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
recording.TotalDepletionCumQty = &total
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *recordingService) attachCumulativeDepletions(ctx context.Context, recordings []entity.Recording) error {
|
||||
if len(recordings) == 0 {
|
||||
return nil
|
||||
}
|
||||
for i := range recordings {
|
||||
if err := s.attachCumulativeDepletion(ctx, &recordings[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *recordingService) attachDepletionRate(ctx context.Context, recording *entity.Recording) error {
|
||||
if recording == nil {
|
||||
return nil
|
||||
}
|
||||
current := 0.0
|
||||
if recording.TotalDepletionQty != nil {
|
||||
current = *recording.TotalDepletionQty
|
||||
}
|
||||
day := 0
|
||||
if recording.Day != nil {
|
||||
day = *recording.Day
|
||||
}
|
||||
prev, err := s.Repository.FindPreviousRecording(s.Repository.DB().WithContext(ctx), recording.ProjectFlockKandangId, day)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
totalChick, err := s.Repository.GetTotalChick(s.Repository.DB().WithContext(ctx), recording.ProjectFlockKandangId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rate := computeDepletionRate(prev, current, totalChick)
|
||||
recording.DepletionRate = &rate
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *recordingService) attachDepletionRates(ctx context.Context, recordings []entity.Recording) error {
|
||||
if len(recordings) == 0 {
|
||||
return nil
|
||||
}
|
||||
for i := range recordings {
|
||||
if err := s.attachDepletionRate(ctx, &recordings[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *recordingService) createRecordingApproval(
|
||||
ctx context.Context,
|
||||
db *gorm.DB,
|
||||
|
||||
Reference in New Issue
Block a user