From 67ddd8e667cf51ee773a07fea9561fe542fc60db Mon Sep 17 00:00:00 2001 From: aguhh18 Date: Wed, 24 Dec 2025 09:24:32 +0700 Subject: [PATCH] Feat[BE]: enhance chickin stock management with FIFO service integration and fix key naming inconsistencies --- .../modules/production/chickins/module.go | 8 ++-- .../chickins/services/chickin.service.go | 38 +++++++++---------- internal/route/route.go | 8 ++-- internal/utils/fifo/constants.go | 2 +- 4 files changed, 26 insertions(+), 30 deletions(-) diff --git a/internal/modules/production/chickins/module.go b/internal/modules/production/chickins/module.go index df0ebd26..2cd0ad7e 100644 --- a/internal/modules/production/chickins/module.go +++ b/internal/modules/production/chickins/module.go @@ -39,19 +39,19 @@ func (ChickinModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validate * projectFlockRepo := rProjectFlock.NewProjectflockRepository(db) productWarehouseRepo := rProductWarehouse.NewProductWarehouseRepository(db) stockAllocationRepo := commonRepo.NewStockAllocationRepository(db) - + fifoService := commonSvc.NewFifoService(db, stockAllocationRepo, productWarehouseRepo, utils.Log) userRepo := rUser.NewUserRepository(db) - fifoService := commonSvc.NewFifoService(db, stockAllocationRepo, productWarehouseRepo, utils.Log) + // Register PROJECT_CHICKIN as usable if err := fifoService.RegisterUsable(fifo.UsableConfig{ - Key: fifo.UsablekeyProjectChickin, + Key: fifo.UsableKeyProjectChickin, Table: "project_chickins", Columns: fifo.UsableColumns{ ID: "id", ProductWarehouseID: "product_warehouse_id", UsageQuantity: "usage_qty", PendingQuantity: "pending_usage_qty", - CreatedAt: "id", + CreatedAt: "created_at", }, }); err != nil { if !strings.Contains(strings.ToLower(err.Error()), "already registered") { diff --git a/internal/modules/production/chickins/services/chickin.service.go b/internal/modules/production/chickins/services/chickin.service.go index fe78080b..965e39ba 100644 --- a/internal/modules/production/chickins/services/chickin.service.go +++ b/internal/modules/production/chickins/services/chickin.service.go @@ -25,7 +25,7 @@ import ( "gorm.io/gorm" ) -var chickinUsableKey = fifo.UsablekeyProjectChickin +var chickinUsableKey = fifo.UsableKeyProjectChickin type ChickinService interface { GetAll(ctx *fiber.Ctx, params *validation.Query) ([]entity.ProjectChickin, int64, error) @@ -135,8 +135,9 @@ func (s *chickinService) CreateOne(c *fiber.Ctx, req *validation.Create) ([]enti return nil, err } newChikins := make([]*entity.ProjectChickin, 0) + chickinQtyMap := make(map[uint]float64) // Store desired qty for each chickin index - for _, chickinReq := range req.ChickinRequests { + for idx, chickinReq := range req.ChickinRequests { productWarehouse, err := s.ProductWarehouseRepo.GetByID(c.Context(), chickinReq.ProductWarehouseId, nil) if err != nil { @@ -164,7 +165,7 @@ func (s *chickinService) CreateOne(c *fiber.Ctx, req *validation.Create) ([]enti newChickin := &entity.ProjectChickin{ ProjectFlockKandangId: req.ProjectFlockKandangId, ChickInDate: chickinDate, - UsageQty: availableQty, + UsageQty: 0, PendingUsageQty: 0, ProductWarehouseId: chickinReq.ProductWarehouseId, Notes: chickinReq.Note, @@ -172,6 +173,7 @@ func (s *chickinService) CreateOne(c *fiber.Ctx, req *validation.Create) ([]enti } newChikins = append(newChikins, newChickin) + chickinQtyMap[uint(idx)] = availableQty } if len(newChikins) == 0 { @@ -193,24 +195,14 @@ func (s *chickinService) CreateOne(c *fiber.Ctx, req *validation.Create) ([]enti return fiber.NewError(fiber.StatusInternalServerError, "Failed to create chickins") } - for _, chickin := range newChikins { - if err := s.ConsumeChickinStocks(c.Context(), dbTransaction, chickin); err != nil { + for idx, chickin := range newChikins { + desiredQty := chickinQtyMap[uint(idx)] + if err := s.ConsumeChickinStocks(c.Context(), dbTransaction, chickin, desiredQty); err != nil { return err } - - if chickin.PendingUsageQty > 0 { - return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Cannot create chickin %d - insufficient stock. Required: %.0f, Available: %.0f, Pending: %.0f", chickin.Id, chickin.UsageQty+chickin.PendingUsageQty, chickin.UsageQty, chickin.PendingUsageQty)) - } } - warehouseDeltas := make(map[uint]float64) - for _, chickin := range newChikins { - warehouseDeltas[chickin.ProductWarehouseId] -= chickin.UsageQty - } - if err := s.adjustProductWarehouseQuantities(c.Context(), dbTransaction, warehouseDeltas); err != nil { - s.Log.Errorf("Failed to adjust product warehouses: %+v", err) - return err - } + // Note: FIFO Consume already adjusts product warehouse quantities, no need to adjust again latest, err := approvalSvcTx.LatestByTarget(c.Context(), utils.ApprovalWorkflowChickin, projectFlockKandang.Id, nil) if err != nil { @@ -599,19 +591,20 @@ func (s *chickinService) convertChickinsToTarget(ctx *fiber.Ctx, chickins []enti return nil } -func (s *chickinService) ConsumeChickinStocks(ctx context.Context, tx *gorm.DB, chickin *entity.ProjectChickin) error { +func (s *chickinService) ConsumeChickinStocks(ctx context.Context, tx *gorm.DB, chickin *entity.ProjectChickin, desiredQty float64) error { if chickin == nil || s.FifoSvc == nil { return nil } - var desired float64 = chickin.UsageQty + s.Log.Infof("ConsumeChickinStocks: chickin_id=%d, product_warehouse_id=%d, desired_qty=%.3f", + chickin.Id, chickin.ProductWarehouseId, desiredQty) result, err := s.FifoSvc.Consume(ctx, commonSvc.StockConsumeRequest{ UsableKey: chickinUsableKey, UsableID: chickin.Id, ProductWarehouseID: chickin.ProductWarehouseId, - Quantity: desired, - AllowPending: false, + Quantity: desiredQty, + AllowPending: true, Tx: tx, }) if err != nil { @@ -619,6 +612,9 @@ func (s *chickinService) ConsumeChickinStocks(ctx context.Context, tx *gorm.DB, return err } + s.Log.Infof("ConsumeChickinStocks result: usage_qty=%.3f, pending_qty=%.3f, allocated_allocations=%d", + result.UsageQuantity, result.PendingQuantity, len(result.AddedAllocations)) + if err := tx.Model(&entity.ProjectChickin{}).Where("id = ?", chickin.Id).Updates(map[string]interface{}{ "usage_qty": result.UsageQuantity, "pending_usage_qty": result.PendingQuantity, diff --git a/internal/route/route.go b/internal/route/route.go index aa538b0c..877ec875 100644 --- a/internal/route/route.go +++ b/internal/route/route.go @@ -12,15 +12,15 @@ import ( closings "gitlab.com/mbugroup/lti-api.git/internal/modules/closings" constants "gitlab.com/mbugroup/lti-api.git/internal/modules/constants" expenses "gitlab.com/mbugroup/lti-api.git/internal/modules/expenses" + finance "gitlab.com/mbugroup/lti-api.git/internal/modules/finance" inventory "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory" marketing "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing" master "gitlab.com/mbugroup/lti-api.git/internal/modules/master" production "gitlab.com/mbugroup/lti-api.git/internal/modules/production" purchases "gitlab.com/mbugroup/lti-api.git/internal/modules/purchases" + repports "gitlab.com/mbugroup/lti-api.git/internal/modules/repports" ssoModule "gitlab.com/mbugroup/lti-api.git/internal/modules/sso" users "gitlab.com/mbugroup/lti-api.git/internal/modules/users" - repports "gitlab.com/mbugroup/lti-api.git/internal/modules/repports" - finance "gitlab.com/mbugroup/lti-api.git/internal/modules/finance" // MODULE IMPORTS ) @@ -44,8 +44,8 @@ func Routes(app *fiber.App, db *gorm.DB) { expenses.ExpenseModule{}, ssoModule.Module{}, closings.ClosingModule{}, - repports.RepportModule{}, - finance.FinanceModule{}, + repports.RepportModule{}, + finance.FinanceModule{}, // MODULE REGISTRY } diff --git a/internal/utils/fifo/constants.go b/internal/utils/fifo/constants.go index c1a79444..fd0bca06 100644 --- a/internal/utils/fifo/constants.go +++ b/internal/utils/fifo/constants.go @@ -2,5 +2,5 @@ package fifo const ( UsableKeyRecordingStock UsableKey = "RECORDING_STOCK" - UsablekeyProjectChickin UsableKey = "PROJECT_CHICKIN" + UsableKeyProjectChickin UsableKey = "PROJECT_CHICKIN" )