diff --git a/internal/common/service/common.fifo.service.go b/internal/common/service/common.fifo.service.go index 2a65c1b4..b99e6c35 100644 --- a/internal/common/service/common.fifo.service.go +++ b/internal/common/service/common.fifo.service.go @@ -228,7 +228,13 @@ func (s *fifoService) Consume(ctx context.Context, req StockConsumeRequest) (*St switch { case delta > 0: - allocationRes, err := s.allocateFromStock(ctx, tx, productWarehouseID, req.UsableKey, req.UsableID, delta) + + var excludedStockables []fifo.StockableKey + if cfg.ExcludedStockables != nil { + excludedStockables = cfg.ExcludedStockables + } + + allocationRes, err := s.allocateFromStock(ctx, tx, productWarehouseID, req.UsableKey, req.UsableID, delta, excludedStockables) if err != nil { return err } @@ -410,8 +416,9 @@ func (s *fifoService) allocateFromStock( usableKey fifo.UsableKey, usableID uint, requestQty float64, + excludedStockables []fifo.StockableKey, ) (*allocationOutcome, error) { - lots, err := s.fetchStockLots(ctx, tx, productWarehouseID) + lots, err := s.fetchStockLots(ctx, tx, productWarehouseID, excludedStockables) if err != nil { return nil, err } @@ -492,14 +499,24 @@ func (s *fifoService) allocateFromStock( }, nil } -func (s *fifoService) fetchStockLots(ctx context.Context, tx *gorm.DB, productWarehouseID uint) ([]stockLot, error) { +func (s *fifoService) fetchStockLots(ctx context.Context, tx *gorm.DB, productWarehouseID uint, excludedStockables []fifo.StockableKey) ([]stockLot, error) { configs := fifo.Stockables() if len(configs) == 0 { return nil, nil } + // Create exclusion set for faster lookup + excludedSet := make(map[fifo.StockableKey]bool) + for _, key := range excludedStockables { + excludedSet[key] = true + } + var lots []stockLot for key, cfg := range configs { + // Skip excluded stockables + if excludedSet[key] { + continue + } usesNumericTime := cfg.Columns.CreatedAt == cfg.Columns.ID @@ -616,7 +633,13 @@ func (s *fifoService) resolvePendingForWarehouse(ctx context.Context, tx *gorm.D continue } - outcome, err := s.allocateFromStock(ctx, tx, productWarehouseID, candidate.UsableKey, candidate.UsableID, candidate.Pending) + // Get excluded stockables from candidate usable config + var excludedStockables []fifo.StockableKey + if candidate.Config.ExcludedStockables != nil { + excludedStockables = candidate.Config.ExcludedStockables + } + + outcome, err := s.allocateFromStock(ctx, tx, productWarehouseID, candidate.UsableKey, candidate.UsableID, candidate.Pending, excludedStockables) if err != nil { return nil, err } diff --git a/internal/utils/fifo/registry.go b/internal/utils/fifo/registry.go index 61fed294..d9801185 100644 --- a/internal/utils/fifo/registry.go +++ b/internal/utils/fifo/registry.go @@ -54,11 +54,12 @@ type StockableConfig struct { // UsableConfig registers a table that consumes stock (recordings, adjustments, sales, etc). type UsableConfig struct { - Key UsableKey - Table string - Columns UsableColumns - OrderBy []string - Scope QueryScope + Key UsableKey + Table string + Columns UsableColumns + OrderBy []string + Scope QueryScope + ExcludedStockables []StockableKey // Stockables to exclude when consuming stock } var (