[FEAT/BE]Fix remove fcr master data and changes to standart production

This commit is contained in:
ragilap
2026-02-03 17:01:50 +07:00
parent 22038533d7
commit b862fc4113
18 changed files with 155 additions and 159 deletions
@@ -0,0 +1,47 @@
BEGIN;
DO $$
DECLARE
fallback_fcr_id BIGINT;
BEGIN
IF NOT EXISTS (
SELECT 1
FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = 'project_flocks'
AND column_name = 'fcr_id'
) THEN
ALTER TABLE project_flocks
ADD COLUMN fcr_id BIGINT;
END IF;
SELECT id INTO fallback_fcr_id
FROM fcrs
ORDER BY id ASC
LIMIT 1;
IF fallback_fcr_id IS NOT NULL THEN
UPDATE project_flocks
SET fcr_id = fallback_fcr_id
WHERE fcr_id IS NULL;
ALTER TABLE project_flocks
ALTER COLUMN fcr_id SET NOT NULL;
END IF;
IF EXISTS (
SELECT 1
FROM pg_constraint
WHERE conname = 'project_flocks_fcr_id_fkey'
) THEN
ALTER TABLE project_flocks
DROP CONSTRAINT project_flocks_fcr_id_fkey;
END IF;
ALTER TABLE project_flocks
ADD CONSTRAINT project_flocks_fcr_id_fkey
FOREIGN KEY (fcr_id) REFERENCES fcrs(id)
ON DELETE RESTRICT ON UPDATE CASCADE;
END $$;
COMMIT;
@@ -0,0 +1,26 @@
BEGIN;
DO $$
BEGIN
IF EXISTS (
SELECT 1
FROM information_schema.columns
WHERE table_schema = 'public'
AND table_name = 'project_flocks'
AND column_name = 'fcr_id'
) THEN
IF EXISTS (
SELECT 1
FROM pg_constraint
WHERE conname = 'project_flocks_fcr_id_fkey'
) THEN
ALTER TABLE project_flocks
DROP CONSTRAINT project_flocks_fcr_id_fkey;
END IF;
ALTER TABLE project_flocks
DROP COLUMN fcr_id;
END IF;
END $$;
COMMIT;
-2
View File
@@ -11,7 +11,6 @@ type ProjectFlock struct {
FlockName string `gorm:"type:varchar(255);not null;uniqueIndex"` FlockName string `gorm:"type:varchar(255);not null;uniqueIndex"`
AreaId uint `gorm:"not null"` AreaId uint `gorm:"not null"`
Category string `gorm:"type:varchar(20);not null"` Category string `gorm:"type:varchar(20);not null"`
FcrId uint `gorm:"not null"`
ProductionStandardId uint `gorm:"column:production_standard_id"` ProductionStandardId uint `gorm:"column:production_standard_id"`
LocationId uint `gorm:"not null"` LocationId uint `gorm:"not null"`
CreatedBy uint `gorm:"not null"` CreatedBy uint `gorm:"not null"`
@@ -20,7 +19,6 @@ type ProjectFlock struct {
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"` DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
Area Area `gorm:"foreignKey:AreaId;references:Id"` Area Area `gorm:"foreignKey:AreaId;references:Id"`
Fcr Fcr `gorm:"foreignKey:FcrId;references:Id"`
ProductionStandard ProductionStandard `gorm:"foreignKey:ProductionStandardId;references:Id"` ProductionStandard ProductionStandard `gorm:"foreignKey:ProductionStandardId;references:Id"`
Location Location `gorm:"foreignKey:LocationId;references:Id"` Location Location `gorm:"foreignKey:LocationId;references:Id"`
CreatedUser User `gorm:"foreignKey:CreatedBy;references:Id"` CreatedUser User `gorm:"foreignKey:CreatedBy;references:Id"`
@@ -24,7 +24,6 @@ type ClosingRepository interface {
SumMarketingWeightAndQtyByProjectFlockKandangIDs(ctx context.Context, projectFlockKandangIDs []uint) (float64, float64, float64, error) SumMarketingWeightAndQtyByProjectFlockKandangIDs(ctx context.Context, projectFlockKandangIDs []uint) (float64, float64, float64, error)
SumMarketingWeightAndQtyByProjectFlockKandangIDsAndFlagNames(ctx context.Context, projectFlockKandangIDs []uint, flagNames []string) (float64, float64, float64, error) SumMarketingWeightAndQtyByProjectFlockKandangIDsAndFlagNames(ctx context.Context, projectFlockKandangIDs []uint, flagNames []string) (float64, float64, float64, error)
SumRecordingEggQtyByProjectFlockKandangIDsAndFlagNames(ctx context.Context, projectFlockKandangIDs []uint, flagNames []string) (float64, error) SumRecordingEggQtyByProjectFlockKandangIDsAndFlagNames(ctx context.Context, projectFlockKandangIDs []uint, flagNames []string) (float64, error)
GetFcrStandardsByFcrID(ctx context.Context, fcrID uint) ([]entity.FcrStandard, error)
GetExpeditionHPP(ctx context.Context, projectFlockID uint, projectFlockKandangID *uint) ([]ExpeditionHPPRow, error) GetExpeditionHPP(ctx context.Context, projectFlockID uint, projectFlockKandangID *uint) ([]ExpeditionHPPRow, error)
FetchSapronakIncoming(ctx context.Context, kandangID uint) ([]SapronakIncomingRow, error) FetchSapronakIncoming(ctx context.Context, kandangID uint) ([]SapronakIncomingRow, error)
FetchSapronakIncomingDetails(ctx context.Context, kandangID uint) (map[uint][]SapronakDetailRow, error) FetchSapronakIncomingDetails(ctx context.Context, kandangID uint) (map[uint][]SapronakDetailRow, error)
@@ -393,22 +392,6 @@ func (r *ClosingRepositoryImpl) SumRecordingEggQtyByProjectFlockKandangIDsAndFla
return agg.TotalQty, nil return agg.TotalQty, nil
} }
func (r *ClosingRepositoryImpl) GetFcrStandardsByFcrID(ctx context.Context, fcrID uint) ([]entity.FcrStandard, error) {
if fcrID == 0 {
return []entity.FcrStandard{}, nil
}
var standards []entity.FcrStandard
if err := r.DB().WithContext(ctx).
Where("fcr_id = ?", fcrID).
Order("weight ASC").
Find(&standards).Error; err != nil {
return nil, err
}
return standards, nil
}
func (r *ClosingRepositoryImpl) GetExpeditionHPP(ctx context.Context, projectFlockID uint, projectFlockKandangID *uint) ([]ExpeditionHPPRow, error) { func (r *ClosingRepositoryImpl) GetExpeditionHPP(ctx context.Context, projectFlockID uint, projectFlockKandangID *uint) ([]ExpeditionHPPRow, error) {
db := r.DB().WithContext(ctx) db := r.DB().WithContext(ctx)
@@ -836,14 +836,6 @@ func (s closingService) GetClosingDataProduksi(c *fiber.Ctx, projectFlockID uint
finalPopulation := population - claimCulling finalPopulation := population - claimCulling
var standards []entity.FcrStandard
if project.FcrId > 0 {
standards, err = s.Repository.GetFcrStandardsByFcrID(c.Context(), project.FcrId)
if err != nil {
s.Log.Errorf("Failed to fetch FCR standards for project flock %d: %+v", projectFlockID, err)
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to fetch FCR standard data")
}
}
age, err := s.calculateAverageSalesAge(c.Context(), projectFlockID, kandangID) age, err := s.calculateAverageSalesAge(c.Context(), projectFlockID, kandangID)
if err != nil { if err != nil {
s.Log.Errorf("Failed to calculate sales age for project flock %d: %+v", projectFlockID, err) s.Log.Errorf("Failed to calculate sales age for project flock %d: %+v", projectFlockID, err)
@@ -893,7 +885,7 @@ func (s closingService) GetClosingDataProduksi(c *fiber.Ctx, projectFlockID uint
chickenDepletion = 0 chickenDepletion = 0
} }
chickenPerformance := calculatePerformanceMetrics(chickenAverageWeight, chickenSalesWeight, feedUsed, population, chickenDepletion, age, standards) chickenPerformance := calculatePerformanceMetrics(chickenAverageWeight, chickenSalesWeight, feedUsed, population, chickenDepletion, age)
if fcrActFromRecording != nil { if fcrActFromRecording != nil {
chickenPerformance.FcrAct = *fcrActFromRecording chickenPerformance.FcrAct = *fcrActFromRecording
} }
@@ -943,7 +935,7 @@ func (s closingService) GetClosingDataProduksi(c *fiber.Ctx, projectFlockID uint
eggDepletion = 0 eggDepletion = 0
} }
eggPerf := calculatePerformanceMetrics(averageEggWeight, eggSalesWeight, feedUsed, harvestEggQty, eggDepletion, age, standards) eggPerf := calculatePerformanceMetrics(averageEggWeight, eggSalesWeight, feedUsed, harvestEggQty, eggDepletion, age)
if fcrActFromRecording != nil { if fcrActFromRecording != nil {
eggPerf.FcrAct = *fcrActFromRecording eggPerf.FcrAct = *fcrActFromRecording
} }
@@ -1001,10 +993,10 @@ func (s closingService) GetClosingDataProduksi(c *fiber.Ctx, projectFlockID uint
performance.EggMass = eggMass performance.EggMass = eggMass
} }
} }
performance.DeffFcr = performance.FcrStd - performance.FcrAct
if productionStandardDetail != nil { if productionStandardDetail != nil {
if productionStandardDetail.StandardFCR != nil { if productionStandardDetail.StandardFCR != nil {
performance.FcrStd = *productionStandardDetail.StandardFCR performance.FcrStd = *productionStandardDetail.StandardFCR
performance.DeffFcr = performance.FcrStd - performance.FcrAct
} }
if !isGrowing { if !isGrowing {
if productionStandardDetail.TargetHenDayProduction != nil { if productionStandardDetail.TargetHenDayProduction != nil {
@@ -1091,8 +1083,8 @@ func (s closingService) determineProductionWeek(ctx context.Context, projectFloc
return week, nil return week, nil
} }
func calculatePerformanceMetrics(averageWeight, totalWeight, feedUsed, basePopulation, depletion, age float64, standards []entity.FcrStandard) dto.ClosingPerformanceDTO { func calculatePerformanceMetrics(averageWeight, totalWeight, feedUsed, basePopulation, depletion, age float64) dto.ClosingPerformanceDTO {
mortalityStd, fcrStd := closestFcrValues(standards, averageWeight) mortalityStd, fcrStd := 0.0, 0.0
fcrAct := 0.0 fcrAct := 0.0
if totalWeight > 0 { if totalWeight > 0 {
@@ -1124,21 +1116,3 @@ func calculatePerformanceMetrics(averageWeight, totalWeight, feedUsed, basePopul
AwgAct: awg, AwgAct: awg,
} }
} }
func closestFcrValues(standards []entity.FcrStandard, averageWeight float64) (float64, float64) {
if len(standards) == 0 || averageWeight <= 0 {
return 0, 0
}
closest := standards[0]
minDiff := math.Abs(closest.Weight - averageWeight)
for _, std := range standards[1:] {
diff := math.Abs(std.Weight - averageWeight)
if diff < minDiff {
minDiff = diff
closest = std
}
}
return closest.Mortality, closest.FcrNumber
}
@@ -444,30 +444,6 @@ func (r *DashboardRepositoryImpl) standardIDSubquery(filters *validation.Dashboa
return db return db
} }
func (r *DashboardRepositoryImpl) standardSourceSubquery(filters *validation.DashboardFilter) *gorm.DB {
db := r.DB().
Table("project_flocks AS pf").
Select("DISTINCT pf.production_standard_id, pf.fcr_id").
Joins("JOIN project_flock_kandangs AS pfk ON pfk.project_flock_id = pf.id").
Joins("JOIN kandangs AS k ON k.id = pfk.kandang_id").
Where("pf.production_standard_id > 0").
Where("pf.fcr_id > 0")
if filters != nil {
if len(filters.FlockIds) > 0 {
db = db.Where("pf.id IN ?", filters.FlockIds)
}
if len(filters.KandangIds) > 0 {
db = db.Where("k.id IN ?", filters.KandangIds)
}
if len(filters.LokasiIds) > 0 {
db = db.Where("k.location_id IN ?", filters.LokasiIds)
}
}
return db
}
func (r *DashboardRepositoryImpl) GetComparisonSeries(ctx context.Context, start, end time.Time, filters *validation.DashboardFilter, comparisonType string) ([]ComparisonSeries, error) { func (r *DashboardRepositoryImpl) GetComparisonSeries(ctx context.Context, start, end time.Time, filters *validation.DashboardFilter, comparisonType string) ([]ComparisonSeries, error) {
seriesExpr, labelExpr, groupExpr, orderExpr, err := comparisonSeriesColumns(comparisonType) seriesExpr, labelExpr, groupExpr, orderExpr, err := comparisonSeriesColumns(comparisonType)
if err != nil { if err != nil {
@@ -5,7 +5,6 @@ import (
entity "gitlab.com/mbugroup/lti-api.git/internal/entities" entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
areaRelationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/areas/dto" areaRelationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/areas/dto"
fcrRelationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/fcrs/dto"
flockRelationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/flocks/dto" flockRelationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/flocks/dto"
kandangRelationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/dto" kandangRelationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/dto"
locationRelationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/locations/dto" locationRelationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/locations/dto"
@@ -13,6 +12,7 @@ import (
warehouseDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/dto" warehouseDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/dto"
pfutils "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/utils" pfutils "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/utils"
userRelationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/users/dto" userRelationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/users/dto"
"gitlab.com/mbugroup/lti-api.git/internal/utils"
) )
// === DTO Structs (ordered) === // === DTO Structs (ordered) ===
@@ -40,7 +40,7 @@ type ProjectFlockDTO struct {
Category string `json:"category"` Category string `json:"category"`
Flock *flockRelationDTO.FlockRelationDTO `json:"flock"` Flock *flockRelationDTO.FlockRelationDTO `json:"flock"`
Area *areaRelationDTO.AreaRelationDTO `json:"area"` Area *areaRelationDTO.AreaRelationDTO `json:"area"`
Fcr *fcrRelationDTO.FcrRelationDTO `json:"fcr"` StandardFcr *float64 `json:"standard_fcr"`
Location *locationRelationDTO.LocationRelationDTO `json:"location"` Location *locationRelationDTO.LocationRelationDTO `json:"location"`
} }
@@ -97,10 +97,6 @@ func ToAreaDTO(e entity.Area) areaRelationDTO.AreaRelationDTO {
return areaRelationDTO.ToAreaRelationDTO(e) return areaRelationDTO.ToAreaRelationDTO(e)
} }
func ToFcrDTO(e entity.Fcr) fcrRelationDTO.FcrRelationDTO {
return fcrRelationDTO.ToFcrRelationDTO(e)
}
func ToLocationDTO(e entity.Location) locationRelationDTO.LocationRelationDTO { func ToLocationDTO(e entity.Location) locationRelationDTO.LocationRelationDTO {
return locationRelationDTO.ToLocationRelationDTO(e) return locationRelationDTO.ToLocationRelationDTO(e)
} }
@@ -121,11 +117,6 @@ func ToProjectFlockDTO(pfk entity.ProjectFlockKandang) ProjectFlockDTO {
mapped := areaRelationDTO.ToAreaRelationDTO(e.Area) mapped := areaRelationDTO.ToAreaRelationDTO(e.Area)
area = &mapped area = &mapped
} }
var fcr *fcrRelationDTO.FcrRelationDTO
if e.Fcr.Id != 0 {
mapped := fcrRelationDTO.ToFcrRelationDTO(e.Fcr)
fcr = &mapped
}
var location *locationRelationDTO.LocationRelationDTO var location *locationRelationDTO.LocationRelationDTO
if e.Location.Id != 0 { if e.Location.Id != 0 {
mapped := locationRelationDTO.ToLocationRelationDTO(e.Location) mapped := locationRelationDTO.ToLocationRelationDTO(e.Location)
@@ -137,7 +128,7 @@ func ToProjectFlockDTO(pfk entity.ProjectFlockKandang) ProjectFlockDTO {
Category: e.Category, Category: e.Category,
Flock: flock, Flock: flock,
Area: area, Area: area,
Fcr: fcr, StandardFcr: resolveProjectFlockStandardFcr(e),
Location: location, Location: location,
} }
} }
@@ -222,6 +213,22 @@ func ToChickinListDTOs(e []entity.ProjectChickin) []ChickinListDTO {
return result return result
} }
func resolveProjectFlockStandardFcr(e entity.ProjectFlock) *float64 {
if e.ProductionStandard.Id == 0 || len(e.ProductionStandard.ProductionStandardDetails) == 0 {
return nil
}
week := 1
if e.Category == string(utils.ProjectFlockCategoryLaying) {
week = 18
}
for _, detail := range e.ProductionStandard.ProductionStandardDetails {
if detail.Week == week && detail.StandardFCR != nil {
return detail.StandardFCR
}
}
return nil
}
func ToChickinSimpleDTOs(e []entity.ProjectChickin) []ChickinSimpleDTO { func ToChickinSimpleDTOs(e []entity.ProjectChickin) []ChickinSimpleDTO {
result := make([]ChickinSimpleDTO, len(e)) result := make([]ChickinSimpleDTO, len(e))
for i, r := range e { for i, r := range e {
@@ -81,7 +81,7 @@ func (s chickinService) withRelations(db *gorm.DB) *gorm.DB {
Preload("ProjectFlockKandang.Kandang.Pic"). Preload("ProjectFlockKandang.Kandang.Pic").
Preload("ProjectFlockKandang.ProjectFlock"). Preload("ProjectFlockKandang.ProjectFlock").
Preload("ProjectFlockKandang.ProjectFlock.Area"). Preload("ProjectFlockKandang.ProjectFlock.Area").
Preload("ProjectFlockKandang.ProjectFlock.Fcr"). Preload("ProjectFlockKandang.ProjectFlock.ProductionStandard.ProductionStandardDetails").
Preload("ProjectFlockKandang.ProjectFlock.Location"). Preload("ProjectFlockKandang.ProjectFlock.Location").
Preload("ProjectFlockKandang.ProjectFlock.Location.Area") Preload("ProjectFlockKandang.ProjectFlock.Location.Area")
@@ -8,7 +8,6 @@ import (
approvalDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/approvals/dto" approvalDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/approvals/dto"
productWarehouseDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/dto" productWarehouseDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/dto"
areaDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/areas/dto" areaDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/areas/dto"
fcrDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/fcrs/dto"
kandangDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/dto" kandangDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/dto"
locationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/locations/dto" locationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/locations/dto"
productionStandardDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/production-standards/dto" productionStandardDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/production-standards/dto"
@@ -31,7 +30,7 @@ type ProjectFlockDTO struct {
projectFlockDTO.ProjectFlockRelationDTO projectFlockDTO.ProjectFlockRelationDTO
Area *areaDTO.AreaRelationDTO `json:"area,omitempty"` Area *areaDTO.AreaRelationDTO `json:"area,omitempty"`
Category string `json:"category"` Category string `json:"category"`
Fcr *fcrDTO.FcrRelationDTO `json:"fcr,omitempty"` StandardFcr *float64 `json:"standard_fcr,omitempty"`
ProductionStandard *productionStandardDTO.ProductionStandardRelationDTO `json:"production_standard,omitempty"` ProductionStandard *productionStandardDTO.ProductionStandardRelationDTO `json:"production_standard,omitempty"`
Location *locationDTO.LocationRelationDTO `json:"location,omitempty"` Location *locationDTO.LocationRelationDTO `json:"location,omitempty"`
CreatedUser *userDTO.UserRelationDTO `json:"created_user,omitempty"` CreatedUser *userDTO.UserRelationDTO `json:"created_user,omitempty"`
@@ -86,7 +85,7 @@ func toProjectFlockDTO(pf *projectFlockDTO.ProjectFlockListDTO) *ProjectFlockDTO
ProjectFlockRelationDTO: pf.ProjectFlockRelationDTO, ProjectFlockRelationDTO: pf.ProjectFlockRelationDTO,
Area: pf.Area, Area: pf.Area,
Category: pf.Category, Category: pf.Category,
Fcr: pf.Fcr, StandardFcr: pf.StandardFcr,
ProductionStandard: pf.ProductionStandard, ProductionStandard: pf.ProductionStandard,
Location: pf.Location, Location: pf.Location,
CreatedUser: pf.CreatedUser, CreatedUser: pf.CreatedUser,
@@ -6,7 +6,6 @@ import (
entity "gitlab.com/mbugroup/lti-api.git/internal/entities" entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
approvalDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/approvals/dto" approvalDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/approvals/dto"
areaDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/areas/dto" areaDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/areas/dto"
fcrDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/fcrs/dto"
kandangDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/dto" kandangDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/dto"
locationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/locations/dto" locationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/locations/dto"
nonstockDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/nonstocks/dto" nonstockDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/nonstocks/dto"
@@ -28,7 +27,7 @@ type ProjectFlockListDTO struct {
ProjectFlockRelationDTO ProjectFlockRelationDTO
Area *areaDTO.AreaRelationDTO `json:"area,omitempty"` Area *areaDTO.AreaRelationDTO `json:"area,omitempty"`
Category string `json:"category"` Category string `json:"category"`
Fcr *fcrDTO.FcrRelationDTO `json:"fcr,omitempty"` StandardFcr *float64 `json:"standard_fcr,omitempty"`
ProductionStandard *productionStandardDTO.ProductionStandardRelationDTO `json:"production_standard,omitempty"` ProductionStandard *productionStandardDTO.ProductionStandardRelationDTO `json:"production_standard,omitempty"`
Location *locationDTO.LocationRelationDTO `json:"location,omitempty"` Location *locationDTO.LocationRelationDTO `json:"location,omitempty"`
Kandangs []KandangWithProjectFlockIdDTO `json:"kandangs,omitempty"` Kandangs []KandangWithProjectFlockIdDTO `json:"kandangs,omitempty"`
@@ -99,12 +98,6 @@ func ToProjectFlockListDTOWithPeriod(e entity.ProjectFlock, period int) ProjectF
areaSummary = &mapped areaSummary = &mapped
} }
var fcrSummary *fcrDTO.FcrRelationDTO
if e.Fcr.Id != 0 {
mapped := fcrDTO.ToFcrRelationDTO(e.Fcr)
fcrSummary = &mapped
}
var productionStandardSummary *productionStandardDTO.ProductionStandardRelationDTO var productionStandardSummary *productionStandardDTO.ProductionStandardRelationDTO
if e.ProductionStandard.Id != 0 { if e.ProductionStandard.Id != 0 {
mapped := productionStandardDTO.ToProductionStandardRelationDTO(e.ProductionStandard) mapped := productionStandardDTO.ToProductionStandardRelationDTO(e.ProductionStandard)
@@ -129,7 +122,7 @@ func ToProjectFlockListDTOWithPeriod(e entity.ProjectFlock, period int) ProjectF
Kandangs: kandangSummaries, Kandangs: kandangSummaries,
ProjectBudgets: ToProjectBudgetDTOs(e.Budgets), ProjectBudgets: ToProjectBudgetDTOs(e.Budgets),
Category: e.Category, Category: e.Category,
Fcr: fcrSummary, StandardFcr: resolveProjectFlockStandardFcr(e),
ProductionStandard: productionStandardSummary, ProductionStandard: productionStandardSummary,
Location: locationSummary, Location: locationSummary,
CreatedAt: e.CreatedAt, CreatedAt: e.CreatedAt,
@@ -204,6 +197,22 @@ func createProjectFlockRelationDTO(e entity.ProjectFlock, period int) ProjectFlo
} }
} }
func resolveProjectFlockStandardFcr(e entity.ProjectFlock) *float64 {
if e.ProductionStandard.Id == 0 || len(e.ProductionStandard.ProductionStandardDetails) == 0 {
return nil
}
week := 1
if e.Category == string(utils.ProjectFlockCategoryLaying) {
week = 18
}
for _, detail := range e.ProductionStandard.ProductionStandardDetails {
if detail.Week == week && detail.StandardFCR != nil {
return detail.StandardFCR
}
}
return nil
}
func ToProjectBudgetDTO(e entity.ProjectBudget) ProjectBudgetDTO { func ToProjectBudgetDTO(e entity.ProjectBudget) ProjectBudgetDTO {
var nonstockRef *nonstockDTO.NonstockRelationDTO var nonstockRef *nonstockDTO.NonstockRelationDTO
if e.Nonstock != nil && e.Nonstock.Id != 0 { if e.Nonstock != nil && e.Nonstock.Id != 0 {
@@ -5,7 +5,6 @@ import (
entity "gitlab.com/mbugroup/lti-api.git/internal/entities" entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
areaDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/areas/dto" areaDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/areas/dto"
fcrDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/fcrs/dto"
kandangDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/dto" kandangDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/dto"
locationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/locations/dto" locationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/locations/dto"
productionStandardDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/production-standards/dto" productionStandardDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/production-standards/dto"
@@ -22,7 +21,7 @@ type ProjectFlockWithPivotDTO struct {
ProjectFlockRelationDTO ProjectFlockRelationDTO
Area *areaDTO.AreaRelationDTO `json:"area,omitempty"` Area *areaDTO.AreaRelationDTO `json:"area,omitempty"`
Category string `json:"category"` Category string `json:"category"`
Fcr *fcrDTO.FcrRelationDTO `json:"fcr,omitempty"` StandardFcr *float64 `json:"standard_fcr,omitempty"`
ProductionStandard *productionStandardDTO.ProductionStandardRelationDTO `json:"production_standard,omitempty"` ProductionStandard *productionStandardDTO.ProductionStandardRelationDTO `json:"production_standard,omitempty"`
ProductionStandardId uint `json:"production_standard_id"` ProductionStandardId uint `json:"production_standard_id"`
Location *locationDTO.LocationRelationDTO `json:"location,omitempty"` Location *locationDTO.LocationRelationDTO `json:"location,omitempty"`
@@ -67,10 +66,6 @@ func ToProjectFlockKandangDTO(e entity.ProjectFlockKandang) ProjectFlockKandangD
mapped := areaDTO.ToAreaRelationDTO(e.ProjectFlock.Area) mapped := areaDTO.ToAreaRelationDTO(e.ProjectFlock.Area)
pfLocal.Area = &mapped pfLocal.Area = &mapped
} }
if e.ProjectFlock.Fcr.Id != 0 {
mapped := fcrDTO.ToFcrRelationDTO(e.ProjectFlock.Fcr)
pfLocal.Fcr = &mapped
}
if e.ProjectFlock.ProductionStandard.Id != 0 { if e.ProjectFlock.ProductionStandard.Id != 0 {
mapped := productionStandardDTO.ToProductionStandardRelationDTO(e.ProjectFlock.ProductionStandard) mapped := productionStandardDTO.ToProductionStandardRelationDTO(e.ProjectFlock.ProductionStandard)
pfLocal.ProductionStandard = &mapped pfLocal.ProductionStandard = &mapped
@@ -83,6 +78,7 @@ func ToProjectFlockKandangDTO(e entity.ProjectFlockKandang) ProjectFlockKandangD
mapped := userDTO.ToUserRelationDTO(e.ProjectFlock.CreatedUser) mapped := userDTO.ToUserRelationDTO(e.ProjectFlock.CreatedUser)
pfLocal.CreatedUser = &mapped pfLocal.CreatedUser = &mapped
} }
pfLocal.StandardFcr = resolveProjectFlockStandardFcr(e.ProjectFlock)
for _, k := range e.ProjectFlock.Kandangs { for _, k := range e.ProjectFlock.Kandangs {
kb := kandangDTO.ToKandangRelationDTO(k) kb := kandangDTO.ToKandangRelationDTO(k)
@@ -23,7 +23,6 @@ type ProjectflockRepository interface {
GetActiveByLocationID(ctx context.Context, locationID uint64) ([]entity.ProjectFlock, error) GetActiveByLocationID(ctx context.Context, locationID uint64) ([]entity.ProjectFlock, error)
IdExists(ctx context.Context, id uint) (bool, error) IdExists(ctx context.Context, id uint) (bool, error)
AreaExists(ctx context.Context, id uint) (bool, error) AreaExists(ctx context.Context, id uint) (bool, error)
FcrExists(ctx context.Context, id uint) (bool, error)
ProductionStandardExists(ctx context.Context, id uint) (bool, error) ProductionStandardExists(ctx context.Context, id uint) (bool, error)
LocationExists(ctx context.Context, id uint) (bool, error) LocationExists(ctx context.Context, id uint) (bool, error)
} }
@@ -67,8 +66,8 @@ func (r *ProjectflockRepositoryImpl) WithDefaultRelations() func(*gorm.DB) *gorm
return db. return db.
Preload("CreatedUser"). Preload("CreatedUser").
Preload("Area"). Preload("Area").
Preload("Fcr").
Preload("ProductionStandard"). Preload("ProductionStandard").
Preload("ProductionStandard.ProductionStandardDetails").
Preload("Location"). Preload("Location").
Preload("Kandangs"). Preload("Kandangs").
Preload("KandangHistory"). Preload("KandangHistory").
@@ -134,14 +133,12 @@ func (r *ProjectflockRepositoryImpl) applySearchFilters(db *gorm.DB, rawSearch s
likeQuery := "%" + normalized + "%" likeQuery := "%" + normalized + "%"
return db. return db.
Joins("LEFT JOIN areas ON areas.id = project_flocks.area_id"). Joins("LEFT JOIN areas ON areas.id = project_flocks.area_id").
Joins("LEFT JOIN fcrs ON fcrs.id = project_flocks.fcr_id").
Joins("LEFT JOIN production_standards ON production_standards.id = project_flocks.production_standard_id"). Joins("LEFT JOIN production_standards ON production_standards.id = project_flocks.production_standard_id").
Joins("LEFT JOIN locations ON locations.id = project_flocks.location_id"). Joins("LEFT JOIN locations ON locations.id = project_flocks.location_id").
Joins("LEFT JOIN users AS created_users ON created_users.id = project_flocks.created_by"). Joins("LEFT JOIN users AS created_users ON created_users.id = project_flocks.created_by").
Where(` Where(`
LOWER(areas.name) LIKE ? LOWER(areas.name) LIKE ?
OR LOWER(project_flocks.category) LIKE ? OR LOWER(project_flocks.category) LIKE ?
OR LOWER(fcrs.name) LIKE ?
OR LOWER(production_standards.name) LIKE ? OR LOWER(production_standards.name) LIKE ?
OR LOWER(locations.name) LIKE ? OR LOWER(locations.name) LIKE ?
OR LOWER(locations.address) LIKE ? OR LOWER(locations.address) LIKE ?
@@ -172,7 +169,6 @@ func (r *ProjectflockRepositoryImpl) applySearchFilters(db *gorm.DB, rawSearch s
likeQuery, likeQuery,
likeQuery, likeQuery,
likeQuery, likeQuery,
likeQuery,
) )
} }
@@ -184,10 +180,6 @@ func (r *ProjectflockRepositoryImpl) AreaExists(ctx context.Context, id uint) (b
return repository.Exists[entity.Area](ctx, r.DB(), id) return repository.Exists[entity.Area](ctx, r.DB(), id)
} }
func (r *ProjectflockRepositoryImpl) FcrExists(ctx context.Context, id uint) (bool, error) {
return repository.Exists[entity.Fcr](ctx, r.DB(), id)
}
func (r *ProjectflockRepositoryImpl) ProductionStandardExists(ctx context.Context, id uint) (bool, error) { func (r *ProjectflockRepositoryImpl) ProductionStandardExists(ctx context.Context, id uint) (bool, error) {
return repository.Exists[entity.ProductionStandard](ctx, r.DB(), id) return repository.Exists[entity.ProductionStandard](ctx, r.DB(), id)
} }
@@ -117,10 +117,10 @@ func (r *projectFlockKandangRepositoryImpl) GetAllWithFilters(ctx context.Contex
Joins("JOIN \"kandangs\" ON \"project_flock_kandangs\".\"kandang_id\" = \"kandangs\".\"id\""). Joins("JOIN \"kandangs\" ON \"project_flock_kandangs\".\"kandang_id\" = \"kandangs\".\"id\"").
Joins("JOIN \"project_flocks\" ON \"project_flock_kandangs\".\"project_flock_id\" = \"project_flocks\".\"id\""). Joins("JOIN \"project_flocks\" ON \"project_flock_kandangs\".\"project_flock_id\" = \"project_flocks\".\"id\"").
Preload("ProjectFlock"). Preload("ProjectFlock").
Preload("ProjectFlock.Fcr").
Preload("ProjectFlock.Area"). Preload("ProjectFlock.Area").
Preload("ProjectFlock.Location"). Preload("ProjectFlock.Location").
Preload("ProjectFlock.CreatedUser"). Preload("ProjectFlock.CreatedUser").
Preload("ProjectFlock.ProductionStandard.ProductionStandardDetails").
Preload("ProjectFlock.Kandangs"). Preload("ProjectFlock.Kandangs").
Preload("ProjectFlock.KandangHistory"). Preload("ProjectFlock.KandangHistory").
Preload("Kandang"). Preload("Kandang").
@@ -208,10 +208,10 @@ func (r *projectFlockKandangRepositoryImpl) GetAllWithFiltersScoped(ctx context.
Joins("JOIN \"kandangs\" ON \"project_flock_kandangs\".\"kandang_id\" = \"kandangs\".\"id\""). Joins("JOIN \"kandangs\" ON \"project_flock_kandangs\".\"kandang_id\" = \"kandangs\".\"id\"").
Joins("JOIN \"project_flocks\" ON \"project_flock_kandangs\".\"project_flock_id\" = \"project_flocks\".\"id\""). Joins("JOIN \"project_flocks\" ON \"project_flock_kandangs\".\"project_flock_id\" = \"project_flocks\".\"id\"").
Preload("ProjectFlock"). Preload("ProjectFlock").
Preload("ProjectFlock.Fcr").
Preload("ProjectFlock.Area"). Preload("ProjectFlock.Area").
Preload("ProjectFlock.Location"). Preload("ProjectFlock.Location").
Preload("ProjectFlock.CreatedUser"). Preload("ProjectFlock.CreatedUser").
Preload("ProjectFlock.ProductionStandard.ProductionStandardDetails").
Preload("ProjectFlock.Kandangs"). Preload("ProjectFlock.Kandangs").
Preload("ProjectFlock.KandangHistory"). Preload("ProjectFlock.KandangHistory").
Preload("Kandang"). Preload("Kandang").
@@ -324,10 +324,10 @@ func (r *projectFlockKandangRepositoryImpl) GetByID(ctx context.Context, id uint
record := new(entity.ProjectFlockKandang) record := new(entity.ProjectFlockKandang)
if err := r.db.WithContext(ctx). if err := r.db.WithContext(ctx).
Preload("ProjectFlock"). Preload("ProjectFlock").
Preload("ProjectFlock.Fcr").
Preload("ProjectFlock.Area"). Preload("ProjectFlock.Area").
Preload("ProjectFlock.Location"). Preload("ProjectFlock.Location").
Preload("ProjectFlock.CreatedUser"). Preload("ProjectFlock.CreatedUser").
Preload("ProjectFlock.ProductionStandard.ProductionStandardDetails").
Preload("ProjectFlock.Kandangs"). Preload("ProjectFlock.Kandangs").
Preload("ProjectFlock.KandangHistory"). Preload("ProjectFlock.KandangHistory").
Preload("Kandang"). Preload("Kandang").
@@ -347,10 +347,10 @@ func (r *projectFlockKandangRepositoryImpl) GetByProjectFlockAndKandang(ctx cont
if err := r.db.WithContext(ctx). if err := r.db.WithContext(ctx).
Where("project_flock_id = ? AND kandang_id = ?", projectFlockID, kandangID). Where("project_flock_id = ? AND kandang_id = ?", projectFlockID, kandangID).
Preload("ProjectFlock"). Preload("ProjectFlock").
Preload("ProjectFlock.Fcr").
Preload("ProjectFlock.Area"). Preload("ProjectFlock.Area").
Preload("ProjectFlock.Location"). Preload("ProjectFlock.Location").
Preload("ProjectFlock.CreatedUser"). Preload("ProjectFlock.CreatedUser").
Preload("ProjectFlock.ProductionStandard.ProductionStandardDetails").
Preload("ProjectFlock.Kandangs"). Preload("ProjectFlock.Kandangs").
Preload("ProjectFlock.KandangHistory"). Preload("ProjectFlock.KandangHistory").
Preload("Kandang"). Preload("Kandang").
@@ -282,7 +282,6 @@ func (s *projectflockService) CreateOne(c *fiber.Ctx, req *validation.Create) (*
if err := commonSvc.EnsureRelations(c.Context(), if err := commonSvc.EnsureRelations(c.Context(),
commonSvc.RelationCheck{Name: "Area", ID: &req.AreaId, Exists: s.Repository.AreaExists}, commonSvc.RelationCheck{Name: "Area", ID: &req.AreaId, Exists: s.Repository.AreaExists},
commonSvc.RelationCheck{Name: "FCR", ID: &req.FcrId, Exists: s.Repository.FcrExists},
commonSvc.RelationCheck{Name: "Production Standard", ID: &req.ProductionStandardId, Exists: s.Repository.ProductionStandardExists}, commonSvc.RelationCheck{Name: "Production Standard", ID: &req.ProductionStandardId, Exists: s.Repository.ProductionStandardExists},
commonSvc.RelationCheck{Name: "Location", ID: &req.LocationId, Exists: s.Repository.LocationExists}, commonSvc.RelationCheck{Name: "Location", ID: &req.LocationId, Exists: s.Repository.LocationExists},
); err != nil { ); err != nil {
@@ -334,7 +333,6 @@ func (s *projectflockService) CreateOne(c *fiber.Ctx, req *validation.Create) (*
createBody := &entity.ProjectFlock{ createBody := &entity.ProjectFlock{
AreaId: req.AreaId, AreaId: req.AreaId,
Category: cat, Category: cat,
FcrId: req.FcrId,
ProductionStandardId: req.ProductionStandardId, ProductionStandardId: req.ProductionStandardId,
LocationId: req.LocationId, LocationId: req.LocationId,
CreatedBy: actorID, CreatedBy: actorID,
@@ -4,7 +4,6 @@ type Create struct {
FlockName string `json:"flock_name" validate:"required_strict"` FlockName string `json:"flock_name" validate:"required_strict"`
AreaId uint `json:"area_id" validate:"required_strict,number,gt=0"` AreaId uint `json:"area_id" validate:"required_strict,number,gt=0"`
Category string `json:"category" validate:"required_strict"` Category string `json:"category" validate:"required_strict"`
FcrId uint `json:"fcr_id" validate:"required_strict,number,gt=0"`
ProductionStandardId uint `json:"production_standard_id" validate:"required_strict,number,gt=0"` ProductionStandardId uint `json:"production_standard_id" validate:"required_strict,number,gt=0"`
LocationId uint `json:"location_id" validate:"required_strict,number,gt=0"` LocationId uint `json:"location_id" validate:"required_strict,number,gt=0"`
KandangIds []uint `json:"kandang_ids" validate:"required,min=1,dive,gt=0"` KandangIds []uint `json:"kandang_ids" validate:"required,min=1,dive,gt=0"`
@@ -280,10 +280,10 @@ func toRecordingProjectFlockDTO(e entity.Recording) RecordingProjectFlockDTO {
} }
} }
if pfk.ProjectFlock.Fcr.Id != 0 || e.StandardFcr != nil { if pfk.ProjectFlock.ProductionStandard.Id != 0 || e.StandardFcr != nil {
result.Fcr = &RecordingFcrDTO{ result.Fcr = &RecordingFcrDTO{
Id: pfk.ProjectFlock.Fcr.Id, Id: pfk.ProjectFlock.ProductionStandard.Id,
Name: pfk.ProjectFlock.Fcr.Name, Name: pfk.ProjectFlock.ProductionStandard.Name,
FcrStd: floatValue(e.StandardFcr), FcrStd: floatValue(e.StandardFcr),
} }
} }
@@ -46,7 +46,6 @@ type RecordingRepository interface {
GetFeedUsageInGrams(tx *gorm.DB, recordingID uint) (float64, error) GetFeedUsageInGrams(tx *gorm.DB, recordingID uint) (float64, error)
GetEggSummaryByRecording(tx *gorm.DB, recordingID uint) (totalQty float64, totalWeightGrams float64, err error) GetEggSummaryByRecording(tx *gorm.DB, recordingID uint) (totalQty float64, totalWeightGrams float64, err error)
GetCumulativeEggQtyByProjectFlockKandang(tx *gorm.DB, projectFlockKandangId uint, recordTime time.Time) (float64, error) GetCumulativeEggQtyByProjectFlockKandang(tx *gorm.DB, projectFlockKandangId uint, recordTime time.Time) (float64, error)
GetFcrStandardNumber(tx *gorm.DB, fcrId uint, currentWeightKg float64) (float64, bool, error)
GetTotalWeightProducedFromUniformityByProjectFlockID(ctx context.Context, projectFlockID uint) (float64, error) GetTotalWeightProducedFromUniformityByProjectFlockID(ctx context.Context, projectFlockID uint) (float64, error)
GetTotalWeightProducedFromUniformityByProjectFlockKandangID(ctx context.Context, projectFlockKandangID uint) (float64, error) GetTotalWeightProducedFromUniformityByProjectFlockKandangID(ctx context.Context, projectFlockKandangID uint) (float64, error)
GetProductionWeightAndQtyByProjectFlockID(ctx context.Context, projectFlockID uint) (totalWeight float64, totalQty float64, err error) GetProductionWeightAndQtyByProjectFlockID(ctx context.Context, projectFlockID uint) (totalWeight float64, totalQty float64, err error)
@@ -92,7 +91,7 @@ func (r *RecordingRepositoryImpl) WithRelations(db *gorm.DB) *gorm.DB {
Preload("ProjectFlockKandang.Kandang.Location"). Preload("ProjectFlockKandang.Kandang.Location").
Preload("ProjectFlockKandang.ProjectFlock"). Preload("ProjectFlockKandang.ProjectFlock").
Preload("ProjectFlockKandang.ProjectFlock.ProductionStandard"). Preload("ProjectFlockKandang.ProjectFlock.ProductionStandard").
Preload("ProjectFlockKandang.ProjectFlock.Fcr"). // Preload("ProjectFlockKandang.ProjectFlock.Fcr").
Preload("Depletions"). Preload("Depletions").
Preload("Depletions.ProductWarehouse"). Preload("Depletions.ProductWarehouse").
Preload("Depletions.ProductWarehouse.Product"). Preload("Depletions.ProductWarehouse.Product").
@@ -448,34 +447,6 @@ func (r *RecordingRepositoryImpl) GetCumulativeEggQtyByProjectFlockKandang(
Scan(&result).Error Scan(&result).Error
return result, err return result, err
} }
func (r *RecordingRepositoryImpl) GetFcrStandardNumber(tx *gorm.DB, fcrId uint, currentWeightKg float64) (float64, bool, error) {
if fcrId == 0 || currentWeightKg <= 0 {
return 0, false, nil
}
var standard entity.FcrStandard
err := tx.
Where("fcr_id = ? AND weight >= ?", fcrId, currentWeightKg).
Order("weight ASC").
First(&standard).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
err = tx.
Where("fcr_id = ?", fcrId).
Order("weight DESC").
First(&standard).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
return 0, false, nil
}
}
if err != nil {
return 0, false, err
}
return standard.FcrNumber, true, nil
}
func (r *RecordingRepositoryImpl) GetProductionWeightAndQtyByProjectFlockID(ctx context.Context, projectFlockID uint) (totalWeight float64, totalQty float64, err error) { func (r *RecordingRepositoryImpl) GetProductionWeightAndQtyByProjectFlockID(ctx context.Context, projectFlockID uint) (totalWeight float64, totalQty float64, err error) {
// Body-weight tracking is removed; keep stub for report compatibility. // Body-weight tracking is removed; keep stub for report compatibility.
return 0, 0, nil return 0, 0, nil
@@ -1352,10 +1352,12 @@ func buildDebtSupplierRow(purchase entity.Purchase, now time.Time, loc *time.Loc
poNumber = *purchase.PoNumber poNumber = *purchase.PoNumber
} }
prDate := purchase.CreatedAt.In(loc) startDate := resolveDebtSupplierReceivedDate(purchase, loc)
startDate := time.Date(prDate.Year(), prDate.Month(), prDate.Day(), 0, 0, 0, 0, loc)
endDate := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, loc) endDate := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, loc)
aging := int(endDate.Sub(startDate).Hours() / 24) aging := 0
if !startDate.IsZero() {
aging = int(endDate.Sub(startDate).Hours() / 24)
}
totalPrice := 0.0 totalPrice := 0.0
travelNumber := "-" travelNumber := "-"
@@ -1525,8 +1527,10 @@ func isDebtSupplierPaid(totalPrice, paymentTotal float64) bool {
} }
func calculateDebtSupplierAging(purchase entity.Purchase, endDate time.Time, loc *time.Location) int { func calculateDebtSupplierAging(purchase entity.Purchase, endDate time.Time, loc *time.Location) int {
prDate := purchase.CreatedAt.In(loc) startDate := resolveDebtSupplierReceivedDate(purchase, loc)
startDate := time.Date(prDate.Year(), prDate.Month(), prDate.Day(), 0, 0, 0, 0, loc) if startDate.IsZero() {
return 0
}
stopDate := time.Date(endDate.Year(), endDate.Month(), endDate.Day(), 0, 0, 0, 0, loc) stopDate := time.Date(endDate.Year(), endDate.Month(), endDate.Day(), 0, 0, 0, 0, loc)
if stopDate.Before(startDate) { if stopDate.Before(startDate) {
return 0 return 0
@@ -1534,6 +1538,23 @@ func calculateDebtSupplierAging(purchase entity.Purchase, endDate time.Time, loc
return int(stopDate.Sub(startDate).Hours() / 24) return int(stopDate.Sub(startDate).Hours() / 24)
} }
func resolveDebtSupplierReceivedDate(purchase entity.Purchase, loc *time.Location) time.Time {
earliest := time.Time{}
for _, item := range purchase.Items {
if item.ReceivedDate == nil || item.ReceivedDate.IsZero() {
continue
}
received := item.ReceivedDate.In(loc)
if earliest.IsZero() || received.Before(earliest) {
earliest = received
}
}
if earliest.IsZero() {
return time.Time{}
}
return time.Date(earliest.Year(), earliest.Month(), earliest.Day(), 0, 0, 0, 0, loc)
}
func (s *repportService) GetHppPerKandang(ctx *fiber.Ctx) (*dto.HppPerKandangResponseData, *dto.HppPerKandangMetaDTO, error) { func (s *repportService) GetHppPerKandang(ctx *fiber.Ctx) (*dto.HppPerKandangResponseData, *dto.HppPerKandangMetaDTO, error) {
params, filters, err := s.parseHppPerKandangQuery(ctx) params, filters, err := s.parseHppPerKandangQuery(ctx)
if err != nil { if err != nil {