init depresiasi

This commit is contained in:
giovanni
2026-04-17 21:26:56 +07:00
parent a54c6184a2
commit fcde3b0a36
34 changed files with 3588 additions and 46 deletions
@@ -419,6 +419,11 @@ func (s *chickinService) CreateOne(c *fiber.Ctx, req *validation.Create) ([]enti
if len(result) == 0 {
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to load created chickins")
}
invalidateFromDate := time.Time{}
for i := range result {
invalidateFromDate = commonSvc.MinNonZeroDateOnlyUTC(invalidateFromDate, result[i].ChickInDate)
}
s.invalidateDepreciationSnapshots(c.Context(), nil, []uint{req.ProjectFlockKandangId}, invalidateFromDate)
return result, nil
}
@@ -462,6 +467,8 @@ func (s chickinService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint)
if err != nil {
return nil, err
}
invalidateFromDate := commonSvc.MinNonZeroDateOnlyUTC(chickin.ChickInDate, updated.ChickInDate)
s.invalidateDepreciationSnapshots(c.Context(), nil, []uint{updated.ProjectFlockKandangId}, invalidateFromDate)
if updated.UsageQty > 0 {
if err := s.syncChickinTraceForProductWarehouse(c.Context(), nil, updated.ProductWarehouseId); err != nil {
@@ -566,6 +573,7 @@ func (s chickinService) DeleteOne(c *fiber.Ctx, id uint) error {
consumeAllocAfter,
traceAllocAfter,
)
s.invalidateDepreciationSnapshots(c.Context(), tx, []uint{lockedChickin.ProjectFlockKandangId}, lockedChickin.ChickInDate)
return nil
})
@@ -1160,6 +1168,7 @@ func (s chickinService) Approval(c *fiber.Ctx, req *validation.Approve) ([]entit
if action == entity.ApprovalActionApproved {
step = utils.ChickinStepDisetujui
}
invalidateFromByPFK := make(map[uint]time.Time, len(approvableIDs))
err = s.Repository.DB().WithContext(c.Context()).Transaction(func(dbTransaction *gorm.DB) error {
if err := s.ensurePopulationRouteScope(c.Context(), dbTransaction); err != nil {
@@ -1204,6 +1213,12 @@ func (s chickinService) Approval(c *fiber.Ctx, req *validation.Approve) ([]entit
if err != nil {
return fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Failed to get chickins for approval %d", approvableID))
}
for _, chickin := range chickins {
invalidateFromByPFK[approvableID] = commonSvc.MinNonZeroDateOnlyUTC(
invalidateFromByPFK[approvableID],
chickin.ChickInDate,
)
}
kandangForApproval, err := s.ProjectflockKandangRepo.GetByID(c.Context(), approvableID)
if err != nil {
@@ -1281,6 +1296,12 @@ func (s chickinService) Approval(c *fiber.Ctx, req *validation.Approve) ([]entit
if err != nil {
return fiber.NewError(fiber.StatusInternalServerError, fmt.Sprintf("Failed to get pending chickins for rejection %d", approvableID))
}
for _, chickin := range chickins {
invalidateFromByPFK[approvableID] = commonSvc.MinNonZeroDateOnlyUTC(
invalidateFromByPFK[approvableID],
chickin.ChickInDate,
)
}
if len(chickins) == 0 {
continue
@@ -1328,6 +1349,9 @@ func (s chickinService) Approval(c *fiber.Ctx, req *validation.Approve) ([]entit
}
return nil, fiber.NewError(fiber.StatusInternalServerError, "Failed to record approval")
}
for projectFlockKandangID, invalidateFromDate := range invalidateFromByPFK {
s.invalidateDepreciationSnapshots(c.Context(), nil, []uint{projectFlockKandangID}, invalidateFromDate)
}
updated := make([]entity.ProjectChickin, 0)
for _, kandangID := range approvableIDs {
@@ -1837,6 +1861,57 @@ func normalizeDateOnlyUTC(value time.Time) time.Time {
return time.Date(value.UTC().Year(), value.UTC().Month(), value.UTC().Day(), 0, 0, 0, 0, time.UTC)
}
func (s chickinService) invalidateDepreciationSnapshots(
ctx context.Context,
tx *gorm.DB,
projectFlockKandangIDs []uint,
fromDate time.Time,
) {
if fromDate.IsZero() {
return
}
projectFlockKandangIDs = uniqueUint(projectFlockKandangIDs)
if len(projectFlockKandangIDs) == 0 {
return
}
targetDB := s.Repository.DB()
if tx != nil {
targetDB = tx
}
farmIDs, err := commonSvc.ResolveProjectFlockIDsByProjectFlockKandangIDs(ctx, targetDB, projectFlockKandangIDs)
if err != nil {
s.Log.Warnf(
"Failed to resolve farm ids for chickin depreciation invalidation (pfk_ids=%v): %+v",
projectFlockKandangIDs,
err,
)
farmIDs = nil
}
if len(farmIDs) == 0 {
if err := commonSvc.InvalidateFarmDepreciationSnapshotsFromDate(ctx, targetDB, nil, fromDate); err != nil {
s.Log.Warnf(
"Failed to invalidate depreciation snapshots globally (from=%s): %+v",
fromDate.Format("2006-01-02"),
err,
)
}
return
}
if err := commonSvc.InvalidateFarmDepreciationSnapshotsFromDate(ctx, targetDB, farmIDs, fromDate); err != nil {
s.Log.Warnf(
"Failed to invalidate depreciation snapshots (farm_ids=%v, from=%s): %+v",
farmIDs,
fromDate.Format("2006-01-02"),
err,
)
}
}
func (s *chickinService) syncChickinTraceForProductWarehouse(ctx context.Context, tx *gorm.DB, productWarehouseID uint) error {
if productWarehouseID == 0 {
return nil
@@ -13,11 +13,11 @@ func ProjectFlockKandangRoutes(v1 fiber.Router, u user.UserService, s projectFlo
ctrl := controller.NewProjectFlockKandangController(s)
route := v1.Group("/project-flock-kandangs")
route.Use(m.Auth(u))
route.Get("/",m.RequirePermissions(m.P_ProjectFlockKandangsGetAll), ctrl.GetAll)
route.Get("/:id",m.RequirePermissions(m.P_ProjectFlockKandangsGetOne), ctrl.GetOne)
// route.Use(m.Auth(u))
route.Get("/", ctrl.GetAll)
route.Get("/:id", m.RequirePermissions(m.P_ProjectFlockKandangsGetOne), ctrl.GetOne)
// route.Post("/:id/closing", m.RequirePermissions(m.PermissionProjectFlockClosing), ctrl.Closing)
// route.Get("/:id/closing/check", m.RequirePermissions(m.PermissionProjectFlockClosing), ctrl.CheckClosing)
route.Post("/:id/closing",m.RequirePermissions(m.P_ProjectFlockKandangsClosing), ctrl.Closing)
route.Post("/:id/closing", m.RequirePermissions(m.P_ProjectFlockKandangsClosing), ctrl.Closing)
route.Get("/:id/closing/check", m.RequirePermissions(m.P_ProjectFlockKandangsCheckClosing), ctrl.CheckClosing)
}
@@ -517,7 +517,14 @@ func (s *recordingService) CreateOne(c *fiber.Ctx, req *validation.Create) (*ent
return nil, transactionErr
}
return s.GetOne(c, createdRecording.Id)
created, err := s.GetOne(c, createdRecording.Id)
if err != nil {
return nil, err
}
if created != nil {
s.invalidateDepreciationSnapshots(c.Context(), nil, created.ProjectFlockKandangId, created.RecordDatetime)
}
return created, nil
}
func (s recordingService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint) (*entity.Recording, error) {
@@ -848,6 +855,13 @@ func (s recordingService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uin
if err := recordingutil.AttachProductionStandards(ctx, s.Repository.DB(), false, s.Log, updatedRecording); err != nil {
return nil, err
}
invalidateFromDate := commonSvc.MinNonZeroDateOnlyUTC(recordingEntity.RecordDatetime, updatedRecording.RecordDatetime)
s.invalidateDepreciationSnapshots(
c.Context(),
nil,
updatedRecording.ProjectFlockKandangId,
invalidateFromDate,
)
return updatedRecording, nil
}
@@ -965,6 +979,12 @@ func (s recordingService) Approval(c *fiber.Ctx, req *validation.Approve) ([]ent
if err != nil {
return nil, err
}
s.invalidateDepreciationSnapshots(
c.Context(),
nil,
recording.ProjectFlockKandangId,
recording.RecordDatetime,
)
updated = append(updated, *recording)
}
@@ -985,7 +1005,7 @@ func (s recordingService) DeleteOne(c *fiber.Ctx, id uint) error {
}
note := recordingutil.RecordingNote("Delete", id)
return s.Repository.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error {
err = s.Repository.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error {
recording, err := s.Repository.WithTx(tx).GetByID(ctx, id, nil)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
@@ -1029,9 +1049,60 @@ func (s recordingService) DeleteOne(c *fiber.Ctx, id uint) error {
s.Log.Errorf("Failed to recalculate recordings after delete: %+v", err)
return err
}
s.invalidateDepreciationSnapshots(ctx, tx, recording.ProjectFlockKandangId, recording.RecordDatetime)
return nil
})
if err != nil {
return err
}
return nil
}
func (s recordingService) invalidateDepreciationSnapshots(
ctx context.Context,
tx *gorm.DB,
projectFlockKandangID uint,
fromDate time.Time,
) {
if projectFlockKandangID == 0 || fromDate.IsZero() {
return
}
targetDB := s.Repository.DB()
if tx != nil {
targetDB = tx
}
farmIDs, err := commonSvc.ResolveProjectFlockIDsByProjectFlockKandangIDs(ctx, targetDB, []uint{projectFlockKandangID})
if err != nil {
s.Log.Warnf(
"Failed to resolve farm for recording depreciation invalidation (pfk=%d): %+v",
projectFlockKandangID,
err,
)
farmIDs = nil
}
if len(farmIDs) == 0 {
if err := commonSvc.InvalidateFarmDepreciationSnapshotsFromDate(ctx, targetDB, nil, fromDate); err != nil {
s.Log.Warnf(
"Failed to invalidate depreciation snapshots globally (from=%s): %+v",
fromDate.Format("2006-01-02"),
err,
)
}
return
}
if err := commonSvc.InvalidateFarmDepreciationSnapshotsFromDate(ctx, targetDB, farmIDs, fromDate); err != nil {
s.Log.Warnf(
"Failed to invalidate depreciation snapshots (farm_ids=%v, from=%s): %+v",
farmIDs,
fromDate.Format("2006-01-02"),
err,
)
}
}
func (s *recordingService) resolveRecordingCategory(ctx context.Context, recording *entity.Recording) (string, error) {
@@ -377,6 +377,7 @@ func (s *transferLayingService) CreateOne(c *fiber.Ctx, req *validation.Create)
if err != nil {
return nil, err
}
s.invalidateDepreciationSnapshots(c.Context(), nil, []uint{req.TargetProjectFlockId}, transferDate)
return laying_transfer, nil
}
@@ -588,6 +589,13 @@ func (s *transferLayingService) UpdateOne(c *fiber.Ctx, req *validation.Update,
}
layingTransfer, _, err := s.GetOne(c, id)
invalidateFromDate := commonSvc.MinNonZeroDateOnlyUTC(existingTransfer.TransferDate, transferDate)
s.invalidateDepreciationSnapshots(
c.Context(),
nil,
[]uint{existingTransfer.ToProjectFlockId, req.TargetProjectFlockId},
invalidateFromDate,
)
return layingTransfer, err
}
@@ -661,6 +669,7 @@ func (s transferLayingService) DeleteOne(c *fiber.Ctx, id uint) error {
s.Log.Errorf("Failed to delete transferLaying: %+v", err)
return fiber.NewError(fiber.StatusInternalServerError, "Failed to delete transfer laying")
}
s.invalidateDepreciationSnapshots(c.Context(), nil, []uint{transfer.ToProjectFlockId}, transfer.TransferDate)
return nil
}
@@ -798,6 +807,14 @@ func (s transferLayingService) Approval(c *fiber.Ctx, req *validation.Approve) (
if err != nil {
return nil, err
}
if transfer != nil {
s.invalidateDepreciationSnapshots(
c.Context(),
nil,
[]uint{transfer.ToProjectFlockId},
resolveDepreciationEffectiveDateForTransfer(transfer),
)
}
updated = append(updated, *transfer)
}
@@ -837,6 +854,14 @@ func (s transferLayingService) Execute(c *fiber.Ctx, id uint) (*entity.LayingTra
if err != nil {
return nil, err
}
if transfer != nil {
s.invalidateDepreciationSnapshots(
c.Context(),
nil,
[]uint{transfer.ToProjectFlockId},
resolveDepreciationEffectiveDateForTransfer(transfer),
)
}
return transfer, nil
}
@@ -873,6 +898,14 @@ func (s transferLayingService) ExecuteWithBusinessDate(c *fiber.Ctx, id uint, bu
if err != nil {
return nil, err
}
if transfer != nil {
s.invalidateDepreciationSnapshots(
c.Context(),
nil,
[]uint{transfer.ToProjectFlockId},
resolveDepreciationEffectiveDateForTransfer(transfer),
)
}
return transfer, nil
}
@@ -1226,6 +1259,14 @@ func (s transferLayingService) Unexecute(c *fiber.Ctx, id uint) (*entity.LayingT
if err != nil {
return nil, err
}
if transfer != nil {
s.invalidateDepreciationSnapshots(
c.Context(),
nil,
[]uint{transfer.ToProjectFlockId},
resolveDepreciationEffectiveDateForTransfer(transfer),
)
}
return transfer, nil
}
@@ -1678,6 +1719,43 @@ func normalizeDateOnlyUTC(value time.Time) time.Time {
return time.Date(value.UTC().Year(), value.UTC().Month(), value.UTC().Day(), 0, 0, 0, 0, time.UTC)
}
func resolveDepreciationEffectiveDateForTransfer(transfer *entity.LayingTransfer) time.Time {
if transfer == nil {
return time.Time{}
}
if transfer.EffectiveMoveDate != nil && !transfer.EffectiveMoveDate.IsZero() {
return *transfer.EffectiveMoveDate
}
if transfer.EconomicCutoffDate != nil && !transfer.EconomicCutoffDate.IsZero() {
return *transfer.EconomicCutoffDate
}
return transfer.TransferDate
}
func (s transferLayingService) invalidateDepreciationSnapshots(
ctx context.Context,
tx *gorm.DB,
farmIDs []uint,
fromDate time.Time,
) {
if fromDate.IsZero() {
return
}
targetDB := s.Repository.DB()
if tx != nil {
targetDB = tx
}
uniqueFarmIDs := utils.UniqueUintSlice(farmIDs)
if err := commonSvc.InvalidateFarmDepreciationSnapshotsFromDate(ctx, targetDB, uniqueFarmIDs, fromDate); err != nil {
s.Log.Warnf(
"Failed to invalidate farm depreciation snapshots (farms=%v, from=%s): %+v",
uniqueFarmIDs,
fromDate.Format("2006-01-02"),
err,
)
}
}
func isLegacyTransfer(transfer *entity.LayingTransfer) bool {
if transfer == nil {
return false