mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
adjust api production-result
This commit is contained in:
@@ -12,6 +12,7 @@ import (
|
|||||||
|
|
||||||
expenseRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/repositories"
|
expenseRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses/repositories"
|
||||||
marketingRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/repositories"
|
marketingRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/repositories"
|
||||||
|
productionStandardRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/master/production-standards/repositories"
|
||||||
chickinRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/production/chickins/repositories"
|
chickinRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/production/chickins/repositories"
|
||||||
recordingRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/production/recordings/repositories"
|
recordingRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/production/recordings/repositories"
|
||||||
purchaseRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/purchases/repositories"
|
purchaseRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/purchases/repositories"
|
||||||
@@ -34,10 +35,26 @@ func (RepportModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validate *
|
|||||||
debtSupplierRepository := repportRepo.NewDebtSupplierRepository(db)
|
debtSupplierRepository := repportRepo.NewDebtSupplierRepository(db)
|
||||||
hppPerKandangRepository := repportRepo.NewHppPerKandangRepository(db)
|
hppPerKandangRepository := repportRepo.NewHppPerKandangRepository(db)
|
||||||
productionResultRepository := repportRepo.NewProductionResultRepository(db)
|
productionResultRepository := repportRepo.NewProductionResultRepository(db)
|
||||||
|
standardGrowthDetailRepository := productionStandardRepo.NewStandardGrowthDetailRepository(db)
|
||||||
|
productionStandardDetailRepository := productionStandardRepo.NewProductionStandardDetailRepository(db)
|
||||||
userRepository := rUser.NewUserRepository(db)
|
userRepository := rUser.NewUserRepository(db)
|
||||||
|
|
||||||
approvalSvc := approvalService.NewApprovalService(approvalRepository)
|
approvalSvc := approvalService.NewApprovalService(approvalRepository)
|
||||||
repportService := sRepport.NewRepportService(validate, expenseRealizationRepository, marketingDeliveryProductRepository, purchaseRepository, chickinRepository, recordingRepository, approvalSvc, purchaseSupplierRepository, debtSupplierRepository, hppPerKandangRepository, productionResultRepository)
|
repportService := sRepport.NewRepportService(
|
||||||
|
validate,
|
||||||
|
expenseRealizationRepository,
|
||||||
|
marketingDeliveryProductRepository,
|
||||||
|
purchaseRepository,
|
||||||
|
chickinRepository,
|
||||||
|
recordingRepository,
|
||||||
|
approvalSvc,
|
||||||
|
purchaseSupplierRepository,
|
||||||
|
debtSupplierRepository,
|
||||||
|
hppPerKandangRepository,
|
||||||
|
productionResultRepository,
|
||||||
|
standardGrowthDetailRepository,
|
||||||
|
productionStandardDetailRepository,
|
||||||
|
)
|
||||||
userService := sUser.NewUserService(userRepository, validate)
|
userService := sUser.NewUserService(userRepository, validate)
|
||||||
|
|
||||||
RepportRoutes(router, userService, repportService)
|
RepportRoutes(router, userService, repportService)
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
|
|
||||||
type ProductionResultRepository interface {
|
type ProductionResultRepository interface {
|
||||||
GetRecordingsByProjectFlockKandang(ctx context.Context, projectFlockKandangID uint, offset, limit int) ([]entity.Recording, int64, error)
|
GetRecordingsByProjectFlockKandang(ctx context.Context, projectFlockKandangID uint, offset, limit int) ([]entity.Recording, int64, error)
|
||||||
|
GetProductionStandardIDByProjectFlockKandangID(ctx context.Context, projectFlockKandangID uint) (uint, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type productionResultRepositoryImpl struct {
|
type productionResultRepositoryImpl struct {
|
||||||
@@ -76,3 +77,25 @@ func (r *productionResultRepositoryImpl) GetRecordingsByProjectFlockKandang(
|
|||||||
|
|
||||||
return recordings, total, nil
|
return recordings, total, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *productionResultRepositoryImpl) GetProductionStandardIDByProjectFlockKandangID(ctx context.Context, projectFlockKandangID uint) (uint, error) {
|
||||||
|
if projectFlockKandangID == 0 {
|
||||||
|
return 0, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var row struct {
|
||||||
|
ProductionStandardID uint `gorm:"column:production_standard_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
err := r.db.WithContext(ctx).
|
||||||
|
Table("project_flock_kandangs pfk").
|
||||||
|
Select("pf.production_standard_id").
|
||||||
|
Joins("JOIN project_flocks pf ON pf.id = pfk.project_flock_id").
|
||||||
|
Where("pfk.id = ?", projectFlockKandangID).
|
||||||
|
Take(&row).Error
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return row.ProductionStandardID, nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -21,6 +22,7 @@ import (
|
|||||||
areaDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/areas/dto"
|
areaDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/areas/dto"
|
||||||
supplierDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/suppliers/dto"
|
supplierDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/suppliers/dto"
|
||||||
warehouseDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/dto"
|
warehouseDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/dto"
|
||||||
|
productionStandardRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/production-standards/repositories"
|
||||||
chickinRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/production/chickins/repositories"
|
chickinRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/production/chickins/repositories"
|
||||||
recordingRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/production/recordings/repositories"
|
recordingRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/production/recordings/repositories"
|
||||||
purchaseRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/purchases/repositories"
|
purchaseRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/purchases/repositories"
|
||||||
@@ -55,6 +57,8 @@ type repportService struct {
|
|||||||
DebtSupplierRepo repportRepo.DebtSupplierRepository
|
DebtSupplierRepo repportRepo.DebtSupplierRepository
|
||||||
HppPerKandangRepo repportRepo.HppPerKandangRepository
|
HppPerKandangRepo repportRepo.HppPerKandangRepository
|
||||||
ProductionResultRepo repportRepo.ProductionResultRepository
|
ProductionResultRepo repportRepo.ProductionResultRepository
|
||||||
|
StandardGrowthDetailRepo productionStandardRepository.StandardGrowthDetailRepository
|
||||||
|
ProductionStandardDetailRepo productionStandardRepository.ProductionStandardDetailRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
type HppCostAggregate struct {
|
type HppCostAggregate struct {
|
||||||
@@ -78,6 +82,8 @@ func NewRepportService(
|
|||||||
debtSupplierRepo repportRepo.DebtSupplierRepository,
|
debtSupplierRepo repportRepo.DebtSupplierRepository,
|
||||||
hppPerKandangRepo repportRepo.HppPerKandangRepository,
|
hppPerKandangRepo repportRepo.HppPerKandangRepository,
|
||||||
productionResultRepo repportRepo.ProductionResultRepository,
|
productionResultRepo repportRepo.ProductionResultRepository,
|
||||||
|
standardGrowthDetailRepo productionStandardRepository.StandardGrowthDetailRepository,
|
||||||
|
productionStandardDetailRepo productionStandardRepository.ProductionStandardDetailRepository,
|
||||||
) RepportService {
|
) RepportService {
|
||||||
return &repportService{
|
return &repportService{
|
||||||
Log: utils.Log,
|
Log: utils.Log,
|
||||||
@@ -92,6 +98,8 @@ func NewRepportService(
|
|||||||
DebtSupplierRepo: debtSupplierRepo,
|
DebtSupplierRepo: debtSupplierRepo,
|
||||||
HppPerKandangRepo: hppPerKandangRepo,
|
HppPerKandangRepo: hppPerKandangRepo,
|
||||||
ProductionResultRepo: productionResultRepo,
|
ProductionResultRepo: productionResultRepo,
|
||||||
|
StandardGrowthDetailRepo: standardGrowthDetailRepo,
|
||||||
|
ProductionStandardDetailRepo: productionStandardDetailRepo,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,6 +293,21 @@ func (s *repportService) GetProductionResult(ctx *fiber.Ctx, params *validation.
|
|||||||
|
|
||||||
weeklyResults := summarizeProductionResults(dailyResults, recordsPerWeek)
|
weeklyResults := summarizeProductionResults(dailyResults, recordsPerWeek)
|
||||||
|
|
||||||
|
var productionStandardID uint
|
||||||
|
if s.ProductionResultRepo != nil {
|
||||||
|
standardID, err := s.ProductionResultRepo.GetProductionStandardIDByProjectFlockKandangID(ctx.Context(), params.ProjectFlockKandangID)
|
||||||
|
if err != nil {
|
||||||
|
if !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||||
|
return nil, 0, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
productionStandardID = standardID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
standardDetailCache := make(map[int]*entity.ProductionStandardDetail)
|
||||||
|
growthDetailCache := make(map[int]*entity.StandardGrowthDetail)
|
||||||
|
|
||||||
var cumulativeButir int64
|
var cumulativeButir int64
|
||||||
var cumulativeKg float64
|
var cumulativeKg float64
|
||||||
for i := range weeklyResults {
|
for i := range weeklyResults {
|
||||||
@@ -300,6 +323,66 @@ func (s *repportService) GetProductionResult(ctx *fiber.Ctx, params *validation.
|
|||||||
|
|
||||||
cumulativeKg += weeklyResults[i].KgJumlah
|
cumulativeKg += weeklyResults[i].KgJumlah
|
||||||
weeklyResults[i].TotalKg = cumulativeKg
|
weeklyResults[i].TotalKg = cumulativeKg
|
||||||
|
|
||||||
|
if productionStandardID == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
week := int(weeklyResults[i].Woa)
|
||||||
|
if s.ProductionStandardDetailRepo != nil {
|
||||||
|
detail, ok := standardDetailCache[week]
|
||||||
|
if !ok {
|
||||||
|
fetched, fetchErr := s.ProductionStandardDetailRepo.GetByStandardIDAndWeek(ctx.Context(), productionStandardID, week)
|
||||||
|
if fetchErr != nil {
|
||||||
|
if !errors.Is(fetchErr, gorm.ErrRecordNotFound) {
|
||||||
|
return nil, 0, fetchErr
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
detail = fetched
|
||||||
|
}
|
||||||
|
standardDetailCache[week] = detail
|
||||||
|
}
|
||||||
|
|
||||||
|
if detail != nil {
|
||||||
|
if detail.TargetHenDayProduction != nil {
|
||||||
|
weeklyResults[i].HdStd = *detail.TargetHenDayProduction
|
||||||
|
}
|
||||||
|
if detail.TargetHenHouseProduction != nil {
|
||||||
|
weeklyResults[i].HhStd = *detail.TargetHenHouseProduction
|
||||||
|
}
|
||||||
|
if detail.TargetEggWeight != nil {
|
||||||
|
weeklyResults[i].EwStd = *detail.TargetEggWeight
|
||||||
|
}
|
||||||
|
if detail.TargetEggMass != nil {
|
||||||
|
weeklyResults[i].EmStd = *detail.TargetEggMass
|
||||||
|
}
|
||||||
|
if detail.StandardFCR != nil {
|
||||||
|
weeklyResults[i].FcrStd = *detail.StandardFCR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if s.StandardGrowthDetailRepo != nil {
|
||||||
|
detail, ok := growthDetailCache[week]
|
||||||
|
if !ok {
|
||||||
|
fetched, fetchErr := s.StandardGrowthDetailRepo.GetByStandardIDAndWeek(ctx.Context(), productionStandardID, week)
|
||||||
|
if fetchErr != nil {
|
||||||
|
if !errors.Is(fetchErr, gorm.ErrRecordNotFound) {
|
||||||
|
return nil, 0, fetchErr
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
detail = fetched
|
||||||
|
}
|
||||||
|
growthDetailCache[week] = detail
|
||||||
|
}
|
||||||
|
|
||||||
|
if detail != nil && detail.FeedIntake != nil {
|
||||||
|
weeklyResults[i].FiStd = *detail.FeedIntake
|
||||||
|
}
|
||||||
|
if detail != nil && detail.TargetMeanBw != nil {
|
||||||
|
weeklyResults[i].StdBw = *detail.TargetMeanBw
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
totalWeeks := int64(math.Ceil(float64(totalRecordings) / float64(recordsPerWeek)))
|
totalWeeks := int64(math.Ceil(float64(totalRecordings) / float64(recordsPerWeek)))
|
||||||
@@ -314,17 +397,17 @@ func mapRecordingToProductionResultDTO(record entity.Recording) dto.ProductionRe
|
|||||||
StdUniformity: "90% up",
|
StdUniformity: "90% up",
|
||||||
DepKum: valueOrZero(record.CumDepletionRate),
|
DepKum: valueOrZero(record.CumDepletionRate),
|
||||||
DepStd: valueOrZero(record.TotalDepletionQty),
|
DepStd: valueOrZero(record.TotalDepletionQty),
|
||||||
|
Hd: valueOrZero(record.HenDay),
|
||||||
|
Fi: valueOrZero(record.FeedIntake),
|
||||||
Fcr: valueOrZero(record.FcrValue),
|
Fcr: valueOrZero(record.FcrValue),
|
||||||
Hh: valueOrZero(record.TotalChickQty),
|
Hh: valueOrZero(record.HenHouse),
|
||||||
|
Em: valueOrZero(record.EggMass),
|
||||||
|
Ew: valueOrZero(record.EggWeight),
|
||||||
}
|
}
|
||||||
|
|
||||||
if record.Day != nil {
|
if record.Day != nil {
|
||||||
result.Woa = float64(*record.Day)
|
result.Woa = float64(*record.Day)
|
||||||
}
|
}
|
||||||
if record.CumIntake != nil {
|
|
||||||
result.Fi = float64(*record.CumIntake)
|
|
||||||
}
|
|
||||||
|
|
||||||
// avgWeight := calculateAverageBodyWeight(record.BodyWeights)
|
// avgWeight := calculateAverageBodyWeight(record.BodyWeights)
|
||||||
avgWeight := 1.0
|
avgWeight := 1.0
|
||||||
if avgWeight > 0 {
|
if avgWeight > 0 {
|
||||||
@@ -351,8 +434,6 @@ func mapRecordingToProductionResultDTO(record entity.Recording) dto.ProductionRe
|
|||||||
result.PersenPutih = roundFloat((float64(result.ButiranPutih)/total)*100, 2)
|
result.PersenPutih = roundFloat((float64(result.ButiranPutih)/total)*100, 2)
|
||||||
result.PersenRetak = roundFloat((float64(result.ButiranRetak)/total)*100, 2)
|
result.PersenRetak = roundFloat((float64(result.ButiranRetak)/total)*100, 2)
|
||||||
result.PersenPecah = roundFloat((float64(result.ButiranPecah)/total)*100, 2)
|
result.PersenPecah = roundFloat((float64(result.ButiranPecah)/total)*100, 2)
|
||||||
result.Ew = (eggSummary.TotalKg * 1000) / total
|
|
||||||
result.Em = eggSummary.TotalKg
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
@@ -464,13 +545,13 @@ func summarizeProductionResults(daily []dto.ProductionResultDTO, groupSize int)
|
|||||||
if end > len(daily) {
|
if end > len(daily) {
|
||||||
end = len(daily)
|
end = len(daily)
|
||||||
}
|
}
|
||||||
result = append(result, aggregateProductionResultGroup(daily[i:end]))
|
result = append(result, aggregateProductionResultGroup(daily[i:end], groupSize))
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func aggregateProductionResultGroup(group []dto.ProductionResultDTO) dto.ProductionResultDTO {
|
func aggregateProductionResultGroup(group []dto.ProductionResultDTO, groupSize int) dto.ProductionResultDTO {
|
||||||
count := len(group)
|
count := len(group)
|
||||||
if count == 0 {
|
if count == 0 {
|
||||||
return dto.ProductionResultDTO{}
|
return dto.ProductionResultDTO{}
|
||||||
@@ -542,6 +623,10 @@ func aggregateProductionResultGroup(group []dto.ProductionResultDTO) dto.Product
|
|||||||
if divider == 0 {
|
if divider == 0 {
|
||||||
divider = 1
|
divider = 1
|
||||||
}
|
}
|
||||||
|
weeklyDivider := float64(groupSize)
|
||||||
|
if weeklyDivider == 0 {
|
||||||
|
weeklyDivider = divider
|
||||||
|
}
|
||||||
|
|
||||||
agg.Bw = sumBw / divider
|
agg.Bw = sumBw / divider
|
||||||
agg.StdBw = sumStdBw / divider
|
agg.StdBw = sumStdBw / divider
|
||||||
@@ -570,17 +655,17 @@ func aggregateProductionResultGroup(group []dto.ProductionResultDTO) dto.Product
|
|||||||
agg.PersenPecah = roundFloat(sumPersenPecah/percentDivider, 2)
|
agg.PersenPecah = roundFloat(sumPersenPecah/percentDivider, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
agg.Hd = sumHd / divider
|
agg.Hd = roundFloat(sumHd/weeklyDivider, 2)
|
||||||
agg.HdStd = sumHdStd / divider
|
agg.HdStd = sumHdStd / divider
|
||||||
agg.Fi = sumFi / divider
|
agg.Fi = roundFloat(sumFi/weeklyDivider, 2)
|
||||||
agg.FiStd = sumFiStd / divider
|
agg.FiStd = sumFiStd / divider
|
||||||
agg.Em = sumEm / divider
|
agg.Em = group[count-1].Em
|
||||||
agg.EmStd = sumEmStd / divider
|
agg.EmStd = sumEmStd / divider
|
||||||
agg.Ew = sumEw / divider
|
agg.Ew = group[count-1].Ew
|
||||||
agg.EwStd = sumEwStd / divider
|
agg.EwStd = sumEwStd / divider
|
||||||
agg.Fcr = sumFcr / divider
|
agg.Fcr = roundFloat(sumFcr/weeklyDivider, 2)
|
||||||
agg.FcrStd = sumFcrStd / divider
|
agg.FcrStd = sumFcrStd / divider
|
||||||
agg.Hh = sumHh / divider
|
agg.Hh = roundFloat(sumHh/weeklyDivider, 2)
|
||||||
agg.HhStd = sumHhStd / divider
|
agg.HhStd = sumHhStd / divider
|
||||||
|
|
||||||
return agg
|
return agg
|
||||||
|
|||||||
Reference in New Issue
Block a user