mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
Fix logic recording transition
This commit is contained in:
@@ -3,6 +3,7 @@ package dto
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gitlab.com/mbugroup/lti-api.git/internal/config"
|
||||
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||
areaRelationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/areas/dto"
|
||||
flockRelationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/flocks/dto"
|
||||
@@ -35,13 +36,13 @@ type ChickinRelationDTO struct {
|
||||
}
|
||||
|
||||
type ProjectFlockDTO struct {
|
||||
Id uint `json:"id"`
|
||||
Period int `json:"period"`
|
||||
Category string `json:"category"`
|
||||
Flock *flockRelationDTO.FlockRelationDTO `json:"flock"`
|
||||
Area *areaRelationDTO.AreaRelationDTO `json:"area"`
|
||||
StandardFcr *float64 `json:"standard_fcr"`
|
||||
Location *locationRelationDTO.LocationRelationDTO `json:"location"`
|
||||
Id uint `json:"id"`
|
||||
Period int `json:"period"`
|
||||
Category string `json:"category"`
|
||||
Flock *flockRelationDTO.FlockRelationDTO `json:"flock"`
|
||||
Area *areaRelationDTO.AreaRelationDTO `json:"area"`
|
||||
StandardFcr *float64 `json:"standard_fcr"`
|
||||
Location *locationRelationDTO.LocationRelationDTO `json:"location"`
|
||||
}
|
||||
|
||||
type ProjectFlockKandangDTO struct {
|
||||
@@ -123,13 +124,13 @@ func ToProjectFlockDTO(pfk entity.ProjectFlockKandang) ProjectFlockDTO {
|
||||
location = &mapped
|
||||
}
|
||||
return ProjectFlockDTO{
|
||||
Id: e.Id,
|
||||
Period: pfk.Period,
|
||||
Category: e.Category,
|
||||
Flock: flock,
|
||||
Area: area,
|
||||
Id: e.Id,
|
||||
Period: pfk.Period,
|
||||
Category: e.Category,
|
||||
Flock: flock,
|
||||
Area: area,
|
||||
StandardFcr: resolveProjectFlockStandardFcr(e),
|
||||
Location: location,
|
||||
Location: location,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,7 +220,7 @@ func resolveProjectFlockStandardFcr(e entity.ProjectFlock) *float64 {
|
||||
}
|
||||
week := 1
|
||||
if e.Category == string(utils.ProjectFlockCategoryLaying) {
|
||||
week = 18
|
||||
week = config.LayingWeekStart()
|
||||
}
|
||||
for _, detail := range e.ProductionStandard.ProductionStandardDetails {
|
||||
if detail.Week == week && detail.StandardFCR != nil {
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
warehouseDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/dto"
|
||||
"gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/dto"
|
||||
@@ -272,10 +273,20 @@ func (u *ProjectflockController) LookupProjectFlockKandang(c *fiber.Ctx) error {
|
||||
projectFlockId := c.QueryInt("project_flock_id", 0)
|
||||
kandangId := c.QueryInt("kandang_id", 0)
|
||||
withPopulation := c.QueryBool("withpopulation", false)
|
||||
recordDateRaw := strings.TrimSpace(c.Query("record_date", ""))
|
||||
var recordDate *time.Time
|
||||
|
||||
if projectFlockId == 0 || kandangId == 0 {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid project_flock_id or kandang_id")
|
||||
}
|
||||
if recordDateRaw != "" {
|
||||
parsed, err := time.Parse("2006-01-02", recordDateRaw)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "record_date must be in YYYY-MM-DD format")
|
||||
}
|
||||
utc := parsed.UTC()
|
||||
recordDate = &utc
|
||||
}
|
||||
|
||||
result, availableStock, err := u.ProjectflockService.GetProjectFlockKandangByProjectAndKandang(c, uint(projectFlockId), uint(kandangId))
|
||||
if err != nil {
|
||||
@@ -300,7 +311,7 @@ func (u *ProjectflockController) LookupProjectFlockKandang(c *fiber.Ctx) error {
|
||||
mapped := warehouseDTO.ToWarehouseRelationDTO(*warehouse)
|
||||
dtoResult.Warehouse = &mapped
|
||||
}
|
||||
if isTransition, isLaying, serr := u.ProjectflockService.GetProjectFlockKandangTransferState(c, result.Id); serr != nil {
|
||||
if isTransition, isLaying, serr := u.ProjectflockService.GetProjectFlockKandangTransferStateAtDate(c, result.Id, recordDate); serr != nil {
|
||||
return serr
|
||||
} else {
|
||||
dtoResult.IsTransition = isTransition
|
||||
|
||||
@@ -3,6 +3,7 @@ package dto
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gitlab.com/mbugroup/lti-api.git/internal/config"
|
||||
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||
approvalDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/approvals/dto"
|
||||
areaDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/areas/dto"
|
||||
@@ -25,17 +26,17 @@ type ProjectFlockRelationDTO struct {
|
||||
|
||||
type ProjectFlockListDTO struct {
|
||||
ProjectFlockRelationDTO
|
||||
Area *areaDTO.AreaRelationDTO `json:"area,omitempty"`
|
||||
Category string `json:"category"`
|
||||
StandardFcr *float64 `json:"standard_fcr,omitempty"`
|
||||
Area *areaDTO.AreaRelationDTO `json:"area,omitempty"`
|
||||
Category string `json:"category"`
|
||||
StandardFcr *float64 `json:"standard_fcr,omitempty"`
|
||||
ProductionStandard *productionStandardDTO.ProductionStandardRelationDTO `json:"production_standard,omitempty"`
|
||||
Location *locationDTO.LocationRelationDTO `json:"location,omitempty"`
|
||||
Kandangs []KandangWithProjectFlockIdDTO `json:"kandangs,omitempty"`
|
||||
ProjectBudgets []ProjectBudgetDTO `json:"project_budgets,omitempty"`
|
||||
CreatedUser *userDTO.UserRelationDTO `json:"created_user"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
Approval approvalDTO.ApprovalRelationDTO `json:"approval"`
|
||||
Location *locationDTO.LocationRelationDTO `json:"location,omitempty"`
|
||||
Kandangs []KandangWithProjectFlockIdDTO `json:"kandangs,omitempty"`
|
||||
ProjectBudgets []ProjectBudgetDTO `json:"project_budgets,omitempty"`
|
||||
CreatedUser *userDTO.UserRelationDTO `json:"created_user"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
Approval approvalDTO.ApprovalRelationDTO `json:"approval"`
|
||||
}
|
||||
|
||||
type KandangWithProjectFlockIdDTO struct {
|
||||
@@ -203,7 +204,7 @@ func resolveProjectFlockStandardFcr(e entity.ProjectFlock) *float64 {
|
||||
}
|
||||
week := 1
|
||||
if e.Category == string(utils.ProjectFlockCategoryLaying) {
|
||||
week = 18
|
||||
week = config.LayingWeekStart()
|
||||
}
|
||||
for _, detail := range e.ProductionStandard.ProductionStandardDetails {
|
||||
if detail.Week == week && detail.StandardFCR != nil {
|
||||
|
||||
@@ -46,6 +46,7 @@ type ProjectflockService interface {
|
||||
GetProjectFlockKandangPopulation(ctx *fiber.Ctx, projectFlockKandangID uint) (float64, error)
|
||||
GetProjectFlockKandangChickinDate(ctx *fiber.Ctx, projectFlockKandangID uint) (*time.Time, error)
|
||||
GetProjectFlockKandangTransferState(ctx *fiber.Ctx, projectFlockKandangID uint) (bool, bool, error)
|
||||
GetProjectFlockKandangTransferStateAtDate(ctx *fiber.Ctx, projectFlockKandangID uint, referenceDate *time.Time) (bool, bool, error)
|
||||
GetPeriodSummary(ctx *fiber.Ctx, locationID uint) ([]KandangPeriodSummary, error)
|
||||
GetProjectPeriods(ctx *fiber.Ctx, projectIDs []uint) (map[uint]int, error)
|
||||
Approval(ctx *fiber.Ctx, req *validation.Approve) ([]entity.ProjectFlock, error)
|
||||
@@ -544,6 +545,10 @@ func (s projectflockService) GetProjectFlockKandangChickinDate(ctx *fiber.Ctx, p
|
||||
}
|
||||
|
||||
func (s projectflockService) GetProjectFlockKandangTransferState(ctx *fiber.Ctx, projectFlockKandangID uint) (bool, bool, error) {
|
||||
return s.GetProjectFlockKandangTransferStateAtDate(ctx, projectFlockKandangID, nil)
|
||||
}
|
||||
|
||||
func (s projectflockService) GetProjectFlockKandangTransferStateAtDate(ctx *fiber.Ctx, projectFlockKandangID uint, referenceDate *time.Time) (bool, bool, error) {
|
||||
if projectFlockKandangID == 0 || s.TransferLayingRepo == nil || s.PivotRepo == nil {
|
||||
return false, false, nil
|
||||
}
|
||||
@@ -593,9 +598,12 @@ func (s projectflockService) GetProjectFlockKandangTransferState(ctx *fiber.Ctx,
|
||||
economicCutoffDate = physicalMoveDate
|
||||
}
|
||||
|
||||
referenceDate := normalizeDateOnlyUTC(time.Now().UTC())
|
||||
isTransition := !referenceDate.Before(physicalMoveDate) && referenceDate.Before(economicCutoffDate)
|
||||
isLaying := !referenceDate.Before(economicCutoffDate)
|
||||
reference := normalizeDateOnlyUTC(time.Now().UTC())
|
||||
if referenceDate != nil && !referenceDate.IsZero() {
|
||||
reference = normalizeDateOnlyUTC(referenceDate.UTC())
|
||||
}
|
||||
isTransition := !reference.Before(physicalMoveDate) && reference.Before(economicCutoffDate)
|
||||
isLaying := !reference.Before(economicCutoffDate)
|
||||
|
||||
return isTransition, isLaying, nil
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"gitlab.com/mbugroup/lti-api.git/internal/config"
|
||||
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||
approvalDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/approvals/dto"
|
||||
productWarehouseDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/adjustments/dto"
|
||||
@@ -308,7 +309,7 @@ func recordingWeekValue(e entity.Recording) int {
|
||||
}
|
||||
weekBase := 1
|
||||
if isLayingRecording(e) {
|
||||
weekBase = 18
|
||||
weekBase = config.LayingWeekStart()
|
||||
}
|
||||
return ((day - 1) / 7) + weekBase
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@ type RecordingRepository interface {
|
||||
GetLatestAvgWeightByProjectFlockID(ctx context.Context, projectFlockID uint) (avgWeight float64, err error)
|
||||
GetTotalEggProductionWeightByProjectFlockID(ctx context.Context, projectFlockID uint) (totalWeightKg float64, err error)
|
||||
GetAverageTargetMetricsByProjectFlockKandangID(ctx context.Context, projectFlockKandangID uint, includeTargets bool) (RecordingTargetAverages, error)
|
||||
GetProjectFlockKandangIDsByPopulationWarehouseIDs(ctx context.Context, tx *gorm.DB, productWarehouseIDs []uint) ([]uint, error)
|
||||
ResyncProjectFlockPopulationUsage(ctx context.Context, tx *gorm.DB, projectFlockKandangID uint) error
|
||||
ValidateProductWarehousesByFlags(ctx context.Context, ids []uint, flags []string) (uint, error)
|
||||
}
|
||||
@@ -874,6 +875,34 @@ func (r *RecordingRepositoryImpl) GetAverageTargetMetricsByProjectFlockKandangID
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (r *RecordingRepositoryImpl) GetProjectFlockKandangIDsByPopulationWarehouseIDs(
|
||||
ctx context.Context,
|
||||
tx *gorm.DB,
|
||||
productWarehouseIDs []uint,
|
||||
) ([]uint, error) {
|
||||
if len(productWarehouseIDs) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
db := r.DB().WithContext(ctx)
|
||||
if tx != nil {
|
||||
db = tx.WithContext(ctx)
|
||||
}
|
||||
|
||||
var kandangIDs []uint
|
||||
if err := db.Table("project_flock_populations pfp").
|
||||
Select("DISTINCT pc.project_flock_kandang_id").
|
||||
Joins("JOIN project_chickins pc ON pc.id = pfp.project_chickin_id").
|
||||
Where("pfp.product_warehouse_id IN ?", productWarehouseIDs).
|
||||
Where("pfp.deleted_at IS NULL").
|
||||
Where("pc.deleted_at IS NULL").
|
||||
Pluck("pc.project_flock_kandang_id", &kandangIDs).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return kandangIDs, nil
|
||||
}
|
||||
|
||||
func (r *RecordingRepositoryImpl) ResyncProjectFlockPopulationUsage(ctx context.Context, tx *gorm.DB, projectFlockKandangID uint) error {
|
||||
if projectFlockKandangID == 0 {
|
||||
return nil
|
||||
|
||||
@@ -1039,11 +1039,75 @@ func (s *recordingService) evaluatePopulationMutationState(ctx context.Context,
|
||||
populationCanChange := true
|
||||
if category == strings.ToUpper(string(utils.ProjectFlockCategoryGrowing)) {
|
||||
populationCanChange = !(transferExecuted && !recordDate.Before(transferDate))
|
||||
|
||||
if transferExecuted && !recordDate.Before(transferDate) {
|
||||
hasTargetLayingRecording, checkErr := s.hasAnyRecordingOnTransferTargets(ctx, transfer)
|
||||
if checkErr != nil {
|
||||
s.Log.Errorf("Failed to resolve target laying recording state for transfer %d: %+v", transfer.Id, checkErr)
|
||||
return true, false, false, false, nil, time.Time{}, fiber.NewError(fiber.StatusInternalServerError, "Gagal memvalidasi status transisi recording")
|
||||
}
|
||||
if hasTargetLayingRecording {
|
||||
isTransition = false
|
||||
isLaying = true
|
||||
} else {
|
||||
today := normalizeDateOnlyUTC(time.Now().UTC())
|
||||
if !today.Before(economicCutoffDate) {
|
||||
isTransition = true
|
||||
isLaying = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return populationCanChange, transferExecuted, isTransition, isLaying, transfer, transferDate, nil
|
||||
}
|
||||
|
||||
func (s *recordingService) hasAnyRecordingOnTransferTargets(ctx context.Context, transfer *entity.LayingTransfer) (bool, error) {
|
||||
if transfer == nil || transfer.Id == 0 {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
targetIDs, err := s.transferTargetProjectFlockKandangIDs(ctx, transfer.Id)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if len(targetIDs) == 0 {
|
||||
// Keep existing behavior for legacy or incomplete target mapping.
|
||||
return true, nil
|
||||
}
|
||||
|
||||
var count int64
|
||||
err = s.Repository.DB().
|
||||
WithContext(ctx).
|
||||
Table("recordings").
|
||||
Where("deleted_at IS NULL").
|
||||
Where("project_flock_kandangs_id IN ?", targetIDs).
|
||||
Count(&count).Error
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return count > 0, nil
|
||||
}
|
||||
|
||||
func (s *recordingService) transferTargetProjectFlockKandangIDs(ctx context.Context, transferID uint) ([]uint, error) {
|
||||
if transferID == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
var targetIDs []uint
|
||||
err := s.Repository.DB().
|
||||
WithContext(ctx).
|
||||
Table("laying_transfer_targets").
|
||||
Where("laying_transfer_id = ?", transferID).
|
||||
Where("deleted_at IS NULL").
|
||||
Pluck("target_project_flock_kandang_id", &targetIDs).Error
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return targetIDs, nil
|
||||
}
|
||||
|
||||
func (s *recordingService) ensurePopulationMutationAllowed(ctx context.Context, recording *entity.Recording, operation string) error {
|
||||
populationCanChange, _, _, _, transfer, transferDate, err := s.evaluatePopulationMutationState(ctx, recording)
|
||||
if err != nil {
|
||||
@@ -1091,19 +1155,16 @@ func (s *recordingService) ensureDepletionMutationAllowed(ctx context.Context, r
|
||||
category = strings.ToUpper(strings.TrimSpace(pfk.ProjectFlock.Category))
|
||||
}
|
||||
|
||||
if !shouldGuardDepletionMutation(category) {
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
transfer *entity.LayingTransfer
|
||||
err error
|
||||
)
|
||||
|
||||
switch category {
|
||||
case strings.ToUpper(string(utils.ProjectFlockCategoryGrowing)):
|
||||
transfer, err = s.TransferLayingRepo.GetLatestApprovedBySourceKandang(ctx, recording.ProjectFlockKandangId)
|
||||
case strings.ToUpper(string(utils.ProjectFlockCategoryLaying)):
|
||||
transfer, err = s.TransferLayingRepo.GetLatestApprovedByTargetKandang(ctx, recording.ProjectFlockKandangId)
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
transfer, err = s.TransferLayingRepo.GetLatestApprovedBySourceKandang(ctx, recording.ProjectFlockKandangId)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil
|
||||
@@ -1132,6 +1193,10 @@ func (s *recordingService) ensureDepletionMutationAllowed(ctx context.Context, r
|
||||
)
|
||||
}
|
||||
|
||||
func shouldGuardDepletionMutation(category string) bool {
|
||||
return strings.EqualFold(strings.TrimSpace(category), string(utils.ProjectFlockCategoryGrowing))
|
||||
}
|
||||
|
||||
func (s *recordingService) tryAutoExecuteTransferForRecordingCreate(c *fiber.Ctx, pfk *entity.ProjectFlockKandang, recordTime time.Time) error {
|
||||
if pfk == nil || pfk.Id == 0 || s.TransferLayingRepo == nil || s.TransferLayingSvc == nil {
|
||||
return nil
|
||||
@@ -2026,10 +2091,7 @@ func (s *recordingService) reflowApplyRecordingStocks(
|
||||
}
|
||||
s.logStockTrace("reflow_apply:done", *refreshed, fmt.Sprintf("desired=%.3f used=%.3f pending=%.3f", desiredTotal, actualUsage, actualPending))
|
||||
|
||||
logDecrease := actualUsage
|
||||
if actualPending > 0 {
|
||||
logDecrease += actualPending
|
||||
}
|
||||
logDecrease := recordingStockRollbackQty(*refreshed)
|
||||
if logDecrease > 0 && shouldWriteLog {
|
||||
log := &entity.StockLog{
|
||||
ProductWarehouseId: refreshed.ProductWarehouseId,
|
||||
@@ -2073,11 +2135,8 @@ func (s *recordingService) reflowResetRecordingStocks(
|
||||
continue
|
||||
}
|
||||
|
||||
currentUsage := 0.0
|
||||
if stock.UsageQty != nil {
|
||||
currentUsage = *stock.UsageQty
|
||||
}
|
||||
s.logStockTrace("reflow_reset:start", stock, "")
|
||||
rollbackQty := recordingStockRollbackQty(stock)
|
||||
s.logStockTrace("reflow_reset:start", stock, fmt.Sprintf("rollback_qty=%.3f", rollbackQty))
|
||||
|
||||
if err := s.Repository.UpdateStockUsage(tx, stock.Id, 0, 0); err != nil {
|
||||
return err
|
||||
@@ -2094,13 +2153,13 @@ func (s *recordingService) reflowResetRecordingStocks(
|
||||
s.Log.Errorf("Failed to reflow FIFO v2 rollback for recording stock %d: %+v", stock.Id, err)
|
||||
return err
|
||||
}
|
||||
s.logStockTrace("reflow_reset:done", stock, "")
|
||||
s.logStockTrace("reflow_reset:done", stock, fmt.Sprintf("rollback_qty=%.3f", rollbackQty))
|
||||
|
||||
if currentUsage > 0 && shouldWriteLog {
|
||||
if rollbackQty > 0 && shouldWriteLog {
|
||||
log := &entity.StockLog{
|
||||
ProductWarehouseId: stock.ProductWarehouseId,
|
||||
CreatedBy: actorID,
|
||||
Increase: currentUsage,
|
||||
Increase: rollbackQty,
|
||||
LoggableType: string(utils.StockLogTypeRecording),
|
||||
LoggableId: stock.RecordingId,
|
||||
Notes: note,
|
||||
@@ -2114,6 +2173,24 @@ func (s *recordingService) reflowResetRecordingStocks(
|
||||
return nil
|
||||
}
|
||||
|
||||
func recordingStockRollbackQty(stock entity.RecordingStock) float64 {
|
||||
usage := 0.0
|
||||
if stock.UsageQty != nil {
|
||||
usage = *stock.UsageQty
|
||||
}
|
||||
pending := 0.0
|
||||
if stock.PendingQty != nil {
|
||||
pending = *stock.PendingQty
|
||||
}
|
||||
if usage < 0 {
|
||||
usage = 0
|
||||
}
|
||||
if pending < 0 {
|
||||
pending = 0
|
||||
}
|
||||
return usage + pending
|
||||
}
|
||||
|
||||
type desiredStock struct {
|
||||
Usage float64
|
||||
Pending float64
|
||||
@@ -2627,19 +2704,8 @@ func (s *recordingService) resyncPopulationUsageForDepletions(
|
||||
}
|
||||
|
||||
if len(sourceWarehouseIDs) > 0 {
|
||||
db := s.Repository.DB().WithContext(ctx)
|
||||
if tx != nil {
|
||||
db = tx.WithContext(ctx)
|
||||
}
|
||||
|
||||
var sourceKandangIDs []uint
|
||||
if err := db.Table("project_flock_populations pfp").
|
||||
Select("DISTINCT pc.project_flock_kandang_id").
|
||||
Joins("JOIN project_chickins pc ON pc.id = pfp.project_chickin_id").
|
||||
Where("pfp.product_warehouse_id IN ?", sourceWarehouseIDs).
|
||||
Where("pfp.deleted_at IS NULL").
|
||||
Where("pc.deleted_at IS NULL").
|
||||
Pluck("pc.project_flock_kandang_id", &sourceKandangIDs).Error; err != nil {
|
||||
sourceKandangIDs, err := s.Repository.GetProjectFlockKandangIDsByPopulationWarehouseIDs(ctx, tx, sourceWarehouseIDs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -2651,62 +2717,7 @@ func (s *recordingService) resyncPopulationUsageForDepletions(
|
||||
}
|
||||
|
||||
for kandangID := range kandangIDs {
|
||||
if err := s.resyncPopulationUsageByProjectFlockKandang(ctx, tx, kandangID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *recordingService) resyncPopulationUsageByProjectFlockKandang(ctx context.Context, tx *gorm.DB, projectFlockKandangID uint) error {
|
||||
if projectFlockKandangID == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
db := s.Repository.DB().WithContext(ctx)
|
||||
if tx != nil {
|
||||
db = tx.WithContext(ctx)
|
||||
}
|
||||
|
||||
var populationIDs []uint
|
||||
if err := db.Table("project_flock_populations pfp").
|
||||
Select("pfp.id").
|
||||
Joins("JOIN project_chickins pc ON pc.id = pfp.project_chickin_id").
|
||||
Where("pc.project_flock_kandang_id = ?", projectFlockKandangID).
|
||||
Pluck("pfp.id", &populationIDs).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if len(populationIDs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
type usageRow struct {
|
||||
StockableID uint `gorm:"column:stockable_id"`
|
||||
Used float64 `gorm:"column:used"`
|
||||
}
|
||||
var usageRows []usageRow
|
||||
if err := db.Table("stock_allocations").
|
||||
Select("stockable_id, COALESCE(SUM(qty), 0) AS used").
|
||||
Where("stockable_type = ?", fifo.StockableKeyProjectFlockPopulation.String()).
|
||||
Where("status = ?", entity.StockAllocationStatusActive).
|
||||
Where("allocation_purpose = ?", entity.StockAllocationPurposeConsume).
|
||||
Where("stockable_id IN ?", populationIDs).
|
||||
Group("stockable_id").
|
||||
Scan(&usageRows).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := db.Model(&entity.ProjectFlockPopulation{}).
|
||||
Where("id IN ?", populationIDs).
|
||||
Update("total_used_qty", 0).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, row := range usageRows {
|
||||
if err := db.Model(&entity.ProjectFlockPopulation{}).
|
||||
Where("id = ?", row.StockableID).
|
||||
Update("total_used_qty", row.Used).Error; err != nil {
|
||||
if err := s.Repository.ResyncProjectFlockPopulationUsage(ctx, tx, kandangID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
|
||||
commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository"
|
||||
commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service"
|
||||
"gitlab.com/mbugroup/lti-api.git/internal/config"
|
||||
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
|
||||
rProductionStandard "gitlab.com/mbugroup/lti-api.git/internal/modules/master/production-standards/repositories"
|
||||
@@ -380,12 +381,13 @@ func (s *uniformityService) CreateOne(c *fiber.Ctx, req *validation.Create, file
|
||||
}
|
||||
}
|
||||
weekBase := 1
|
||||
if strings.EqualFold(category, string(utils.ProjectFlockCategoryLaying)) {
|
||||
weekBase = 18
|
||||
isLayingCategory := strings.EqualFold(category, string(utils.ProjectFlockCategoryLaying))
|
||||
if isLayingCategory {
|
||||
weekBase = config.LayingWeekStart()
|
||||
}
|
||||
if req.Week < weekBase {
|
||||
if weekBase == 18 {
|
||||
return nil, fiber.NewError(fiber.StatusBadRequest, "week must start from 18 for laying projects")
|
||||
if isLayingCategory {
|
||||
return nil, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("week must start from %d for laying projects", weekBase))
|
||||
}
|
||||
return nil, fiber.NewError(fiber.StatusBadRequest, "week must start from 1 for growing projects")
|
||||
}
|
||||
@@ -399,8 +401,8 @@ func (s *uniformityService) CreateOne(c *fiber.Ctx, req *validation.Create, file
|
||||
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to validate uniformity week sequence")
|
||||
}
|
||||
if latestWeek == 0 && req.Week != weekBase {
|
||||
if weekBase == 18 {
|
||||
return nil, fiber.NewError(fiber.StatusBadRequest, "week must start from 18 for laying projects")
|
||||
if isLayingCategory {
|
||||
return nil, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("week must start from %d for laying projects", weekBase))
|
||||
}
|
||||
return nil, fiber.NewError(fiber.StatusBadRequest, "week must start from 1 for growing projects")
|
||||
}
|
||||
@@ -474,7 +476,7 @@ func (s *uniformityService) CreateOne(c *fiber.Ctx, req *validation.Create, file
|
||||
}); err != nil {
|
||||
s.Log.Errorf("Failed to create uniformity: %+v", err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if s.DocumentSvc != nil {
|
||||
actorIDCopy := actorID
|
||||
@@ -575,12 +577,13 @@ func (s uniformityService) UpdateOne(c *fiber.Ctx, req *validation.Update, id ui
|
||||
}
|
||||
}
|
||||
weekBase := 1
|
||||
if strings.EqualFold(category, string(utils.ProjectFlockCategoryLaying)) {
|
||||
weekBase = 18
|
||||
isLayingCategory := strings.EqualFold(category, string(utils.ProjectFlockCategoryLaying))
|
||||
if isLayingCategory {
|
||||
weekBase = config.LayingWeekStart()
|
||||
}
|
||||
if targetWeek < weekBase {
|
||||
if weekBase == 18 {
|
||||
return nil, fiber.NewError(fiber.StatusBadRequest, "week must start from 18 for laying projects")
|
||||
if isLayingCategory {
|
||||
return nil, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("week must start from %d for laying projects", weekBase))
|
||||
}
|
||||
return nil, fiber.NewError(fiber.StatusBadRequest, "week must start from 1 for growing projects")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user