Revert "Merge branch 'fix/implement-fifo-v2' into 'dev/fifo-v2'"

This reverts merge request !340
This commit is contained in:
Hafizh A. Y.
2026-02-27 09:37:03 +00:00
parent 915302c445
commit f6c88b773d
28 changed files with 163 additions and 1468 deletions
@@ -312,7 +312,7 @@ func (s *recordingService) CreateOne(c *fiber.Ctx, req *validation.Create) (*ent
return nil, err
}
feedIDs := recordingutil.CollectWarehouseIDs(req.Stocks, func(st validation.Stock) uint { return st.ProductWarehouseId })
if err := s.ensureProductWarehousesByFlags(ctx, feedIDs, []string{"PAKAN", "PRE-STARTER", "STARTER", "FINISHER", "OVK", "OBAT", "VITAMIN", "KIMIA"}, "feed"); err != nil {
if err := s.ensureProductWarehousesByFlags(ctx, feedIDs, []string{"PAKAN", "OVK"}, "feed"); err != nil {
return nil, err
}
depletionIDs := recordingutil.CollectWarehouseIDs(req.Depletions, func(d validation.Depletion) uint { return d.ProductWarehouseId })
@@ -320,7 +320,7 @@ func (s *recordingService) CreateOne(c *fiber.Ctx, req *validation.Create) (*ent
return nil, err
}
eggIDs := recordingutil.CollectWarehouseIDs(req.Eggs, func(e validation.Egg) uint { return e.ProductWarehouseId })
if err := s.ensureProductWarehousesByFlags(ctx, eggIDs, []string{"TELUR", "TELUR-UTUH", "TELUR-PUTIH", "TELUR-RETAK", "TELUR-PECAH", "TELUR-PAPACAL", "TELUR-JUMBO"}, "egg"); err != nil {
if err := s.ensureProductWarehousesByFlags(ctx, eggIDs, []string{"TELUR-UTUH", "TELUR-PECAH", "TELUR-PUTIH", "TELUR-RETAK", "TELUR"}, "egg"); err != nil {
return nil, err
}
actorID, err := m.ActorIDFromContext(c)
@@ -512,7 +512,7 @@ func (s recordingService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uin
return err
}
feedIDs := recordingutil.CollectWarehouseIDs(req.Stocks, func(st validation.Stock) uint { return st.ProductWarehouseId })
if err := s.ensureProductWarehousesByFlags(ctx, feedIDs, []string{"PAKAN", "PRE-STARTER", "STARTER", "FINISHER", "OVK", "OBAT", "VITAMIN", "KIMIA"}, "feed"); err != nil {
if err := s.ensureProductWarehousesByFlags(ctx, feedIDs, []string{"PAKAN", "OVK"}, "feed"); err != nil {
return err
}
if err := s.syncRecordingStocks(ctx, tx, recordingEntity.Id, existingStocks, req.Stocks, note, actorID); err != nil {
@@ -613,7 +613,7 @@ func (s recordingService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uin
return err
}
eggIDs := recordingutil.CollectWarehouseIDs(req.Eggs, func(e validation.Egg) uint { return e.ProductWarehouseId })
if err := s.ensureProductWarehousesByFlags(ctx, eggIDs, []string{"TELUR", "TELUR-UTUH", "TELUR-PUTIH", "TELUR-RETAK", "TELUR-PECAH", "TELUR-PAPACAL", "TELUR-JUMBO"}, "egg"); err != nil {
if err := s.ensureProductWarehousesByFlags(ctx, eggIDs, []string{"TELUR-UTUH", "TELUR-PECAH", "TELUR-PUTIH", "TELUR-RETAK", "TELUR"}, "egg"); err != nil {
return err
}
if err := ensureRecordingEggsUnused(existingEggs); err != nil {
@@ -21,93 +21,7 @@ import (
var recordingStockUsableKey = fifo.UsableKeyRecordingStock
var recordingDepletionUsableKey = fifo.UsableKeyRecordingDepletion
const (
depletionUsageTolerance = 0.000001
recordingFunctionCodeStockOut = "RECORDING_STOCK_OUT"
recordingFunctionCodeDepletionOut = "RECORDING_DEPLETION_OUT"
recordingFunctionCodeDepletionIn = "RECORDING_DEPLETION_IN"
recordingFunctionCodeRecordingEggIn = "RECORDING_EGG_IN"
)
func (s *recordingService) resolveRecordingUsableKey(
ctx context.Context,
tx *gorm.DB,
productWarehouseID uint,
functionCode string,
fallback fifo.UsableKey,
actionLabel string,
) (fifo.UsableKey, error) {
if productWarehouseID == 0 {
return "", fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Product warehouse tidak valid untuk transaksi %s", actionLabel))
}
route, err := commonSvc.ResolveFifoStockV2RouteByProductWarehouseIDAndLane(
ctx,
tx,
productWarehouseID,
functionCode,
commonSvc.FifoStockV2LaneUsable,
)
if err != nil {
return "", fiber.NewError(fiber.StatusInternalServerError, "Failed to resolve FIFO v2 recording route")
}
if route == nil {
return "", fiber.NewError(
fiber.StatusBadRequest,
fmt.Sprintf("Product warehouse %d tidak mendukung transaksi %s pada matrix FIFO v2", productWarehouseID, actionLabel),
)
}
usableKey := fifo.UsableKey(strings.TrimSpace(route.LegacyTypeKey))
if usableKey == "" {
usableKey = fallback
}
if usableKey == "" {
return "", fiber.NewError(fiber.StatusInternalServerError, "FIFO v2 recording route misconfiguration")
}
return usableKey, nil
}
func (s *recordingService) resolveRecordingStockableKey(
ctx context.Context,
tx *gorm.DB,
productWarehouseID uint,
functionCode string,
fallback fifo.StockableKey,
actionLabel string,
) (fifo.StockableKey, error) {
if productWarehouseID == 0 {
return "", fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Product warehouse tidak valid untuk transaksi %s", actionLabel))
}
route, err := commonSvc.ResolveFifoStockV2RouteByProductWarehouseIDAndLane(
ctx,
tx,
productWarehouseID,
functionCode,
commonSvc.FifoStockV2LaneStockable,
)
if err != nil {
return "", fiber.NewError(fiber.StatusInternalServerError, "Failed to resolve FIFO v2 recording route")
}
if route == nil {
return "", fiber.NewError(
fiber.StatusBadRequest,
fmt.Sprintf("Product warehouse %d tidak mendukung transaksi %s pada matrix FIFO v2", productWarehouseID, actionLabel),
)
}
stockableKey := fifo.StockableKey(strings.TrimSpace(route.LegacyTypeKey))
if stockableKey == "" {
stockableKey = fallback
}
if stockableKey == "" {
return "", fiber.NewError(fiber.StatusInternalServerError, "FIFO v2 recording route misconfiguration")
}
return stockableKey, nil
}
const depletionUsageTolerance = 0.000001
func (s *recordingService) logStockTrace(action string, stock entity.RecordingStock, extra string) {
if s == nil || s.Log == nil {
@@ -211,20 +125,8 @@ func (s *recordingService) consumeRecordingStocks(
}
desiredTotal := desired + pending
usableKey, err := s.resolveRecordingUsableKey(
ctx,
tx,
stock.ProductWarehouseId,
recordingFunctionCodeStockOut,
recordingStockUsableKey,
"Recording (Stock)",
)
if err != nil {
return err
}
result, err := s.FifoSvc.Consume(ctx, commonSvc.StockConsumeRequest{
UsableKey: usableKey,
UsableKey: recordingStockUsableKey,
UsableID: stock.Id,
ProductWarehouseID: stock.ProductWarehouseId,
Quantity: desiredTotal,
@@ -307,21 +209,9 @@ func (s *recordingService) consumeRecordingDepletions(
return fiber.NewError(fiber.StatusBadRequest, "Source product warehouse tidak ditemukan untuk depletion")
}
usableKey, err := s.resolveRecordingUsableKey(
ctx,
tx,
sourceWarehouseID,
recordingFunctionCodeDepletionOut,
recordingDepletionUsableKey,
"Recording Depletion (Source)",
)
if err != nil {
return err
}
desired := depletion.Qty + depletion.PendingQty
result, err := s.FifoSvc.Consume(ctx, commonSvc.StockConsumeRequest{
UsableKey: usableKey,
UsableKey: recordingDepletionUsableKey,
UsableID: depletion.Id,
ProductWarehouseID: sourceWarehouseID,
Quantity: desired,
@@ -424,20 +314,8 @@ func (s *recordingService) releaseRecordingStocks(
if stock.Id == 0 {
continue
}
usableKey, err := s.resolveRecordingUsableKey(
ctx,
tx,
stock.ProductWarehouseId,
recordingFunctionCodeStockOut,
recordingStockUsableKey,
"Recording (Stock)",
)
if err != nil {
return err
}
if stock.UsageQty != nil && *stock.UsageQty > 0 {
activeCount, err := s.countActiveAllocations(ctx, tx, usableKey, stock.Id)
activeCount, err := s.countActiveAllocations(ctx, tx, fifo.UsableKeyRecordingStock, stock.Id)
if err != nil {
return err
}
@@ -448,16 +326,16 @@ func (s *recordingService) releaseRecordingStocks(
}
continue
}
if err := s.resyncStockableUsageFromAllocations(ctx, tx, usableKey, stock.Id); err != nil {
if err := s.resyncStockableUsageFromAllocations(ctx, tx, fifo.UsableKeyRecordingStock, stock.Id); err != nil {
return err
}
if err := s.ensureActiveAllocations(ctx, tx, usableKey, stock.Id); err != nil {
if err := s.ensureActiveAllocations(ctx, tx, fifo.UsableKeyRecordingStock, stock.Id); err != nil {
return err
}
}
s.logStockTrace("release:start", stock, "")
if err := s.FifoSvc.ReleaseUsage(ctx, commonSvc.StockReleaseRequest{
UsableKey: usableKey,
UsableKey: recordingStockUsableKey,
UsableID: stock.Id,
Tx: tx,
}); err != nil {
@@ -522,28 +400,8 @@ func (s *recordingService) releaseRecordingDepletions(
if depletion.Id == 0 {
continue
}
sourceWarehouseID := uint(0)
if depletion.SourceProductWarehouseId != nil {
sourceWarehouseID = *depletion.SourceProductWarehouseId
}
if sourceWarehouseID == 0 {
return fiber.NewError(fiber.StatusBadRequest, "Source product warehouse tidak ditemukan untuk depletion")
}
usableKey, err := s.resolveRecordingUsableKey(
ctx,
tx,
sourceWarehouseID,
recordingFunctionCodeDepletionOut,
recordingDepletionUsableKey,
"Recording Depletion (Source)",
)
if err != nil {
return err
}
if depletion.UsageQty > 0 {
activeCount, err := s.countActiveAllocations(ctx, tx, usableKey, depletion.Id)
activeCount, err := s.countActiveAllocations(ctx, tx, fifo.UsableKeyRecordingDepletion, depletion.Id)
if err != nil {
return err
}
@@ -560,10 +418,10 @@ func (s *recordingService) releaseRecordingDepletions(
}
continue
}
if err := s.resyncStockableUsageFromAllocations(ctx, tx, usableKey, depletion.Id); err != nil {
if err := s.resyncStockableUsageFromAllocations(ctx, tx, fifo.UsableKeyRecordingDepletion, depletion.Id); err != nil {
return err
}
if err := s.ensureActiveAllocations(ctx, tx, usableKey, depletion.Id); err != nil {
if err := s.ensureActiveAllocations(ctx, tx, fifo.UsableKeyRecordingDepletion, depletion.Id); err != nil {
return err
}
}
@@ -573,8 +431,15 @@ func (s *recordingService) releaseRecordingDepletions(
return err
}
sourceWarehouseID := uint(0)
if depletion.SourceProductWarehouseId != nil {
sourceWarehouseID = *depletion.SourceProductWarehouseId
}
if sourceWarehouseID == 0 {
return fiber.NewError(fiber.StatusBadRequest, "Source product warehouse tidak ditemukan untuk depletion")
}
if err := s.FifoSvc.ReleaseUsage(ctx, commonSvc.StockReleaseRequest{
UsableKey: usableKey,
UsableKey: recordingDepletionUsableKey,
UsableID: depletion.Id,
Tx: tx,
}); err != nil {
@@ -765,20 +630,9 @@ func (s *recordingService) replenishRecordingEggs(
if egg.Id == 0 || egg.ProductWarehouseId == 0 || egg.Qty <= 0 {
continue
}
stockableKey, err := s.resolveRecordingStockableKey(
ctx,
tx,
egg.ProductWarehouseId,
recordingFunctionCodeRecordingEggIn,
fifo.StockableKeyRecordingEgg,
"Recording Egg",
)
if err != nil {
return err
}
s.logEggTrace("replenish:start", egg, "")
if _, err := s.FifoSvc.Replenish(ctx, commonSvc.StockReplenishRequest{
StockableKey: stockableKey,
StockableKey: fifo.StockableKeyRecordingEgg,
StockableID: egg.Id,
ProductWarehouseID: egg.ProductWarehouseId,
Quantity: float64(egg.Qty),
@@ -836,20 +690,9 @@ func (s *recordingService) replenishRecordingDepletions(
if depletion.Id == 0 || depletion.ProductWarehouseId == 0 || depletion.Qty <= 0 {
continue
}
stockableKey, err := s.resolveRecordingStockableKey(
ctx,
tx,
depletion.ProductWarehouseId,
recordingFunctionCodeDepletionIn,
fifo.StockableKeyRecordingDepletion,
"Recording Depletion (Destination)",
)
if err != nil {
return err
}
s.logDepletionTrace("replenish:start", depletion, "")
if _, err := s.FifoSvc.Replenish(ctx, commonSvc.StockReplenishRequest{
StockableKey: stockableKey,
StockableKey: fifo.StockableKeyRecordingDepletion,
StockableID: depletion.Id,
ProductWarehouseID: depletion.ProductWarehouseId,
Quantity: depletion.Qty,
@@ -881,20 +724,9 @@ func (s *recordingService) reduceRecordingDepletions(
if depletion.Id == 0 || depletion.ProductWarehouseId == 0 || depletion.Qty <= 0 {
continue
}
stockableKey, err := s.resolveRecordingStockableKey(
ctx,
tx,
depletion.ProductWarehouseId,
recordingFunctionCodeDepletionIn,
fifo.StockableKeyRecordingDepletion,
"Recording Depletion (Destination)",
)
if err != nil {
return err
}
s.logDepletionTrace("reduce:start", depletion, "")
if err := s.FifoSvc.AdjustStockableQuantity(ctx, commonSvc.StockAdjustRequest{
StockableKey: stockableKey,
StockableKey: fifo.StockableKeyRecordingDepletion,
StockableID: depletion.Id,
ProductWarehouseID: depletion.ProductWarehouseId,
Quantity: -depletion.Qty,
@@ -926,20 +758,9 @@ func (s *recordingService) reduceRecordingEggs(
if egg.Id == 0 || egg.ProductWarehouseId == 0 || egg.Qty <= 0 {
continue
}
stockableKey, err := s.resolveRecordingStockableKey(
ctx,
tx,
egg.ProductWarehouseId,
recordingFunctionCodeRecordingEggIn,
fifo.StockableKeyRecordingEgg,
"Recording Egg",
)
if err != nil {
return err
}
s.logEggTrace("reduce:start", egg, "")
if err := s.FifoSvc.AdjustStockableQuantity(ctx, commonSvc.StockAdjustRequest{
StockableKey: stockableKey,
StockableKey: fifo.StockableKeyRecordingEgg,
StockableID: egg.Id,
ProductWarehouseID: egg.ProductWarehouseId,
Quantity: -float64(egg.Qty),