mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-23 14:55:42 +00:00
feat(BE):change standart egg in fcr master data
This commit is contained in:
@@ -188,39 +188,92 @@ func (r *DashboardRepositoryImpl) GetStandardFcrWeekly(ctx context.Context, week
|
|||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
source := r.standardSourceSubquery(filters)
|
filterClause := ""
|
||||||
if source == nil {
|
filterArgs := make([]interface{}, 0)
|
||||||
return nil, nil
|
if filters != nil {
|
||||||
|
if len(filters.FlockIds) > 0 {
|
||||||
|
filterClause += " AND pf.id IN ?"
|
||||||
|
filterArgs = append(filterArgs, filters.FlockIds)
|
||||||
|
}
|
||||||
|
if len(filters.KandangIds) > 0 {
|
||||||
|
filterClause += " AND k.id IN ?"
|
||||||
|
filterArgs = append(filterArgs, filters.KandangIds)
|
||||||
|
}
|
||||||
|
if len(filters.LokasiIds) > 0 {
|
||||||
|
filterClause += " AND k.location_id IN ?"
|
||||||
|
filterArgs = append(filterArgs, filters.LokasiIds)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var rows []StandardWeeklyFcrMetric
|
query := fmt.Sprintf(`
|
||||||
db := r.DB().WithContext(ctx).
|
WITH src AS (
|
||||||
Table("standard_growth_details AS sgd").
|
SELECT DISTINCT pf.production_standard_id, pf.fcr_id
|
||||||
Select(`
|
FROM project_flocks pf
|
||||||
sgd.week AS week,
|
JOIN project_flock_kandangs pfk ON pfk.project_flock_id = pf.id
|
||||||
COALESCE(AVG(
|
JOIN kandangs k ON k.id = pfk.kandang_id
|
||||||
COALESCE(
|
WHERE pf.production_standard_id > 0 AND pf.fcr_id > 0
|
||||||
(
|
%s
|
||||||
SELECT fs.fcr_number
|
),
|
||||||
FROM fcr_standards fs
|
actual AS (
|
||||||
WHERE fs.fcr_id = src.fcr_id
|
SELECT u.week AS week,
|
||||||
AND fs.weight >= CASE WHEN sgd.target_mean_bw > 10 THEN sgd.target_mean_bw / 1000 ELSE sgd.target_mean_bw END
|
pf.fcr_id AS fcr_id,
|
||||||
ORDER BY fs.weight ASC
|
AVG((u.chart_data->'statistics'->>'average_weight')::numeric) AS avg_weight
|
||||||
LIMIT 1
|
FROM project_flock_kandang_uniformity u
|
||||||
),
|
JOIN project_flock_kandangs pfk ON pfk.id = u.project_flock_kandang_id
|
||||||
(
|
JOIN project_flocks pf ON pf.id = pfk.project_flock_id
|
||||||
SELECT fs.fcr_number
|
JOIN kandangs k ON k.id = pfk.kandang_id
|
||||||
FROM fcr_standards fs
|
WHERE u.week IN ? AND u.uniform_date IS NOT NULL AND pf.fcr_id > 0
|
||||||
WHERE fs.fcr_id = src.fcr_id
|
%s
|
||||||
ORDER BY fs.weight DESC
|
GROUP BY u.week, pf.fcr_id
|
||||||
LIMIT 1
|
),
|
||||||
)
|
target AS (
|
||||||
)
|
SELECT sgd.week AS week,
|
||||||
), 0) AS std_fcr`).
|
src.fcr_id AS fcr_id,
|
||||||
Joins("JOIN (?) AS src ON src.production_standard_id = sgd.production_standard_id", source).
|
AVG(sgd.target_mean_bw) AS target_mean_bw
|
||||||
Where("sgd.week IN ?", weeks)
|
FROM standard_growth_details sgd
|
||||||
|
JOIN src ON src.production_standard_id = sgd.production_standard_id
|
||||||
|
WHERE sgd.week IN ?
|
||||||
|
GROUP BY sgd.week, src.fcr_id
|
||||||
|
),
|
||||||
|
weights AS (
|
||||||
|
SELECT COALESCE(a.week, t.week) AS week,
|
||||||
|
COALESCE(a.fcr_id, t.fcr_id) AS fcr_id,
|
||||||
|
COALESCE(
|
||||||
|
CASE WHEN a.avg_weight > 10 THEN a.avg_weight / 1000 ELSE a.avg_weight END,
|
||||||
|
CASE WHEN t.target_mean_bw > 10 THEN t.target_mean_bw / 1000 ELSE t.target_mean_bw END
|
||||||
|
) AS weight
|
||||||
|
FROM actual a
|
||||||
|
FULL OUTER JOIN target t ON t.week = a.week AND t.fcr_id = a.fcr_id
|
||||||
|
)
|
||||||
|
SELECT w.week AS week,
|
||||||
|
COALESCE(AVG(
|
||||||
|
COALESCE(
|
||||||
|
(SELECT fs.fcr_number
|
||||||
|
FROM fcr_standards fs
|
||||||
|
WHERE fs.fcr_id = w.fcr_id
|
||||||
|
AND fs.weight >= w.weight
|
||||||
|
ORDER BY fs.weight ASC
|
||||||
|
LIMIT 1),
|
||||||
|
(SELECT fs.fcr_number
|
||||||
|
FROM fcr_standards fs
|
||||||
|
WHERE fs.fcr_id = w.fcr_id
|
||||||
|
ORDER BY fs.weight DESC
|
||||||
|
LIMIT 1)
|
||||||
|
)
|
||||||
|
), 0) AS std_fcr
|
||||||
|
FROM weights w
|
||||||
|
GROUP BY w.week
|
||||||
|
ORDER BY w.week ASC
|
||||||
|
`, filterClause, filterClause)
|
||||||
|
|
||||||
if err := db.Group("sgd.week").Order("sgd.week ASC").Scan(&rows).Error; err != nil {
|
args := make([]interface{}, 0, len(filterArgs)*2+2)
|
||||||
|
args = append(args, filterArgs...)
|
||||||
|
args = append(args, weeks)
|
||||||
|
args = append(args, filterArgs...)
|
||||||
|
args = append(args, weeks)
|
||||||
|
|
||||||
|
var rows []StandardWeeklyFcrMetric
|
||||||
|
if err := r.DB().WithContext(ctx).Raw(query, args...).Scan(&rows).Error; err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -507,37 +507,180 @@ func (s dashboardService) buildComparisonChartsAll(ctx context.Context, startDat
|
|||||||
stdFcr[row.Week] = row.StdFcr
|
stdFcr[row.Week] = row.StdFcr
|
||||||
}
|
}
|
||||||
|
|
||||||
layingWeeks, layingActual := mapComparisonWeeklyMetricRows(layingRows)
|
_, layingActual := mapComparisonWeeklyMetricRows(layingRows)
|
||||||
eggWeightWeeks, eggWeightActual := mapComparisonWeeklyMetricRows(eggWeightRows)
|
_, eggWeightActual := mapComparisonWeeklyMetricRows(eggWeightRows)
|
||||||
feedWeeks, feedActual := mapComparisonWeeklyMetricRows(feedIntakeRows)
|
_, feedActual := mapComparisonWeeklyMetricRows(feedIntakeRows)
|
||||||
fcrWeeks, fcrActual := mapComparisonWeeklyMetricRows(fcrRows)
|
_, fcrActual := mapComparisonWeeklyMetricRows(fcrRows)
|
||||||
deplesiWeeks, deplesiActual := mapComparisonWeeklyMetricRows(deplesiRows)
|
_, deplesiActual := mapComparisonWeeklyMetricRows(deplesiRows)
|
||||||
bodyWeightWeeks, bodyWeightActual, uniformityWeeks, uniformityActual := mapComparisonUniformityRows(uniformityRows)
|
_, bodyWeightActual, _, uniformityActual := mapComparisonUniformityRows(uniformityRows)
|
||||||
|
|
||||||
charts := map[string]dto.DashboardChartDTO{}
|
aggregateActual := buildAggregateComparisonPercent(weeks, seriesRows, aggregateComparisonInput{
|
||||||
if len(bodyWeightWeeks) > 0 {
|
BodyWeightActual: bodyWeightActual,
|
||||||
charts["body_weight"] = buildComparisonPercentChart(seriesRows, bodyWeightWeeks, bodyWeightActual, stdBodyWeight)
|
LayingActual: layingActual,
|
||||||
}
|
EggWeightActual: eggWeightActual,
|
||||||
if len(layingWeeks) > 0 {
|
FeedIntakeActual: feedActual,
|
||||||
charts["laying"] = buildComparisonPercentChart(seriesRows, layingWeeks, layingActual, stdLaying)
|
UniformityActual: uniformityActual,
|
||||||
}
|
FcrActual: fcrActual,
|
||||||
if len(eggWeightWeeks) > 0 {
|
DeplesiActual: deplesiActual,
|
||||||
charts["egg_weight"] = buildComparisonPercentChart(seriesRows, eggWeightWeeks, eggWeightActual, stdEggWeight)
|
StdBodyWeight: stdBodyWeight,
|
||||||
}
|
StdLaying: stdLaying,
|
||||||
if len(feedWeeks) > 0 {
|
StdEggWeight: stdEggWeight,
|
||||||
charts["feed_intake"] = buildComparisonPercentChart(seriesRows, feedWeeks, feedActual, stdFeedIntake)
|
StdFeedIntake: stdFeedIntake,
|
||||||
}
|
StdUniformity: stdUniformity,
|
||||||
if len(uniformityWeeks) > 0 {
|
StdFcr: stdFcr,
|
||||||
charts["uniformity"] = buildComparisonPercentChart(seriesRows, uniformityWeeks, uniformityActual, stdUniformity)
|
StdDeplesi: stdDeplesi,
|
||||||
}
|
})
|
||||||
if len(fcrWeeks) > 0 {
|
|
||||||
charts["fcr"] = buildComparisonPercentChart(seriesRows, fcrWeeks, fcrActual, stdFcr)
|
if len(aggregateActual) == 0 {
|
||||||
}
|
return map[string]dto.DashboardChartDTO{}, nil
|
||||||
if len(deplesiWeeks) > 0 {
|
|
||||||
charts["deplesi"] = buildComparisonPercentChart(seriesRows, deplesiWeeks, deplesiActual, stdDeplesi)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return charts, nil
|
chartKey := strings.ToLower(params.ComparisonType)
|
||||||
|
return map[string]dto.DashboardChartDTO{
|
||||||
|
chartKey: buildComparisonAggregateChart(seriesRows, weeks, aggregateActual),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type aggregateComparisonInput struct {
|
||||||
|
BodyWeightActual map[int]map[uint]float64
|
||||||
|
LayingActual map[int]map[uint]float64
|
||||||
|
EggWeightActual map[int]map[uint]float64
|
||||||
|
FeedIntakeActual map[int]map[uint]float64
|
||||||
|
UniformityActual map[int]map[uint]float64
|
||||||
|
FcrActual map[int]map[uint]float64
|
||||||
|
DeplesiActual map[int]map[uint]float64
|
||||||
|
StdBodyWeight map[int]float64
|
||||||
|
StdLaying map[int]float64
|
||||||
|
StdEggWeight map[int]float64
|
||||||
|
StdFeedIntake map[int]float64
|
||||||
|
StdUniformity map[int]float64
|
||||||
|
StdFcr map[int]float64
|
||||||
|
StdDeplesi map[int]float64
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildAggregateComparisonPercent(weeks []int, seriesRows []repository.ComparisonSeries, input aggregateComparisonInput) map[int]map[uint]float64 {
|
||||||
|
result := map[int]map[uint]float64{}
|
||||||
|
|
||||||
|
for _, week := range weeks {
|
||||||
|
stdBodyWeight := input.StdBodyWeight[week]
|
||||||
|
stdLaying := input.StdLaying[week]
|
||||||
|
stdEggWeight := input.StdEggWeight[week]
|
||||||
|
stdFeedIntake := input.StdFeedIntake[week]
|
||||||
|
stdUniformity := input.StdUniformity[week]
|
||||||
|
stdFcr := input.StdFcr[week]
|
||||||
|
stdDeplesi := input.StdDeplesi[week]
|
||||||
|
|
||||||
|
for _, series := range seriesRows {
|
||||||
|
sum := 0.0
|
||||||
|
count := 0.0
|
||||||
|
|
||||||
|
if percent, ok := higherIsBetterPercent(input.LayingActual, week, series.Id, stdLaying); ok {
|
||||||
|
sum += percent
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
if percent, ok := higherIsBetterPercent(input.EggWeightActual, week, series.Id, stdEggWeight); ok {
|
||||||
|
sum += percent
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
if percent, ok := higherIsBetterPercent(input.UniformityActual, week, series.Id, stdUniformity); ok {
|
||||||
|
sum += percent
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
if percent, ok := lowerIsBetterPercent(input.FcrActual, week, series.Id, stdFcr); ok {
|
||||||
|
sum += percent
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
if percent, ok := lowerIsBetterPercent(input.DeplesiActual, week, series.Id, stdDeplesi); ok {
|
||||||
|
sum += percent
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
if percent, ok := higherIsBetterPercent(input.BodyWeightActual, week, series.Id, stdBodyWeight); ok {
|
||||||
|
sum += percent
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
if percent, ok := lowerIsBetterPercent(input.FeedIntakeActual, week, series.Id, stdFeedIntake); ok {
|
||||||
|
sum += percent
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
|
||||||
|
if count == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if result[week] == nil {
|
||||||
|
result[week] = map[uint]float64{}
|
||||||
|
}
|
||||||
|
result[week][series.Id] = sum / count
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
func higherIsBetterPercent(actual map[int]map[uint]float64, week int, seriesId uint, standard float64) (float64, bool) {
|
||||||
|
if standard <= 0 {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
val, ok := metricValue(actual, week, seriesId)
|
||||||
|
if !ok || val <= 0 {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
return (val / standard) * 100, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func lowerIsBetterPercent(actual map[int]map[uint]float64, week int, seriesId uint, standard float64) (float64, bool) {
|
||||||
|
if standard <= 0 {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
val, ok := metricValue(actual, week, seriesId)
|
||||||
|
if !ok || val <= 0 {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
return (standard / val) * 100, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func metricValue(actual map[int]map[uint]float64, week int, seriesId uint) (float64, bool) {
|
||||||
|
weekRows, ok := actual[week]
|
||||||
|
if !ok {
|
||||||
|
return 0, false
|
||||||
|
}
|
||||||
|
val, ok := weekRows[seriesId]
|
||||||
|
return val, ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildComparisonAggregateChart(seriesRows []repository.ComparisonSeries, weeks []int, actual map[int]map[uint]float64) dto.DashboardChartDTO {
|
||||||
|
series := make([]dto.DashboardChartSeriesDTO, 0, len(seriesRows))
|
||||||
|
for _, sRow := range seriesRows {
|
||||||
|
series = append(series, dto.DashboardChartSeriesDTO{
|
||||||
|
Id: strconv.FormatUint(uint64(sRow.Id), 10),
|
||||||
|
Label: sRow.Label,
|
||||||
|
Unit: "%",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
dataset := make([]map[string]interface{}, 0, len(weeks))
|
||||||
|
for _, week := range weeks {
|
||||||
|
row := map[string]interface{}{
|
||||||
|
"week": week,
|
||||||
|
}
|
||||||
|
values, ok := actual[week]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for _, sRow := range seriesRows {
|
||||||
|
if val, exists := values[sRow.Id]; exists {
|
||||||
|
row[strconv.FormatUint(uint64(sRow.Id), 10)] = roundTo(val, 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(row) > 1 {
|
||||||
|
dataset = append(dataset, row)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return dto.DashboardChartDTO{
|
||||||
|
Series: series,
|
||||||
|
Dataset: dataset,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s dashboardService) standardComparisonMap(ctx context.Context, weeks []int, metric string, filter *validation.DashboardFilter) (map[int]float64, error) {
|
func (s dashboardService) standardComparisonMap(ctx context.Context, weeks []int, metric string, filter *validation.DashboardFilter) (map[int]float64, error) {
|
||||||
|
|||||||
Reference in New Issue
Block a user