mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 21:41:55 +00:00
feat/BE/US-278/TASK-288,289-adjust schema database,Create trigger in expense module, add filter in warehouse linked to project flock, and implement fifo system
This commit is contained in:
@@ -39,7 +39,7 @@ func (RecordingModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validate
|
||||
ProductWarehouseID: "product_warehouse_id",
|
||||
UsageQuantity: "usage_qty",
|
||||
PendingQuantity: "pending_qty",
|
||||
CreatedAt: "created_at",
|
||||
CreatedAt: "id",
|
||||
},
|
||||
}); err != nil {
|
||||
if !strings.Contains(strings.ToLower(err.Error()), "already registered") {
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
rUser "gitlab.com/mbugroup/lti-api.git/internal/modules/users/repositories"
|
||||
sUser "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
|
||||
utils "gitlab.com/mbugroup/lti-api.git/internal/utils"
|
||||
"gitlab.com/mbugroup/lti-api.git/internal/utils/fifo"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
@@ -36,6 +37,7 @@ func (PurchaseModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validate
|
||||
expenseRepository := expenseRepo.NewExpenseRepository(db)
|
||||
expenseRealizationRepo := expenseRepo.NewExpenseRealizationRepository(db)
|
||||
projectFlockKandangRepository := projectFlockKandangRepo.NewProjectFlockKandangRepository(db)
|
||||
stockAllocRepo := commonRepo.NewStockAllocationRepository(db)
|
||||
|
||||
approvalRepo := commonRepo.NewApprovalRepository(db)
|
||||
approvalService := commonSvc.NewApprovalService(approvalRepo)
|
||||
@@ -61,6 +63,20 @@ func (PurchaseModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validate
|
||||
expenseServiceInstance,
|
||||
)
|
||||
|
||||
fifoService := commonSvc.NewFifoService(db, stockAllocRepo, productWarehouseRepo, utils.Log)
|
||||
_ = fifoService.RegisterStockable(fifo.StockableConfig{
|
||||
Key: fifo.StockableKey("PURCHASE_ITEMS"),
|
||||
Table: "purchase_items",
|
||||
Columns: fifo.StockableColumns{
|
||||
ID: "id",
|
||||
ProductWarehouseID: "product_warehouse_id",
|
||||
TotalQuantity: "total_qty",
|
||||
TotalUsedQuantity: "total_used",
|
||||
CreatedAt: "id",
|
||||
},
|
||||
OrderBy: []string{"id ASC"},
|
||||
})
|
||||
|
||||
purchaseService := service.NewPurchaseService(
|
||||
validate,
|
||||
purchaseRepo,
|
||||
@@ -71,6 +87,7 @@ func (PurchaseModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validate
|
||||
projectFlockKandangRepository,
|
||||
approvalService,
|
||||
expenseBridge,
|
||||
fifoService,
|
||||
)
|
||||
|
||||
userRepo := rUser.NewUserRepository(db)
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/purchases/validations"
|
||||
"gitlab.com/mbugroup/lti-api.git/internal/utils"
|
||||
approvalutils "gitlab.com/mbugroup/lti-api.git/internal/utils/approvals"
|
||||
"gitlab.com/mbugroup/lti-api.git/internal/utils/fifo"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
"github.com/gofiber/fiber/v2"
|
||||
@@ -40,7 +41,8 @@ type PurchaseService interface {
|
||||
}
|
||||
|
||||
const (
|
||||
priceTolerance = 0.0001
|
||||
priceTolerance = 0.0001
|
||||
purchaseStockableKey = fifo.StockableKey("PURCHASE_ITEMS")
|
||||
)
|
||||
|
||||
type purchaseService struct {
|
||||
@@ -54,6 +56,7 @@ type purchaseService struct {
|
||||
ProjectFlockKandangRepo projectFlockKandangRepo.ProjectFlockKandangRepository
|
||||
ApprovalSvc commonSvc.ApprovalService
|
||||
ExpenseBridge PurchaseExpenseBridge
|
||||
FifoSvc commonSvc.FifoService
|
||||
approvalWorkflow approvalutils.ApprovalWorkflowKey
|
||||
}
|
||||
|
||||
@@ -72,6 +75,7 @@ func NewPurchaseService(
|
||||
projectFlockKandangRepo projectFlockKandangRepo.ProjectFlockKandangRepository,
|
||||
approvalSvc commonSvc.ApprovalService,
|
||||
expenseBridge PurchaseExpenseBridge,
|
||||
fifoSvc commonSvc.FifoService,
|
||||
) PurchaseService {
|
||||
return &purchaseService{
|
||||
Log: utils.Log,
|
||||
@@ -84,6 +88,7 @@ func NewPurchaseService(
|
||||
ProjectFlockKandangRepo: projectFlockKandangRepo,
|
||||
ApprovalSvc: approvalSvc,
|
||||
ExpenseBridge: expenseBridge,
|
||||
FifoSvc: fifoSvc,
|
||||
approvalWorkflow: utils.ApprovalWorkflowPurchase,
|
||||
}
|
||||
}
|
||||
@@ -712,6 +717,9 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation
|
||||
if warehouseID == 0 {
|
||||
return nil, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Warehouse must be specified for item %d", payload.PurchaseItemID))
|
||||
}
|
||||
if payload.WarehouseID != nil && uint(item.WarehouseId) != warehouseID {
|
||||
return nil, fiber.NewError(fiber.StatusBadRequest, "Receiving does not allow changing warehouse")
|
||||
}
|
||||
|
||||
var receivedQty float64
|
||||
if payload.ReceivedQty != nil {
|
||||
@@ -798,6 +806,11 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation
|
||||
deltas := make(map[uint]float64)
|
||||
affected := make(map[uint]struct{})
|
||||
updates := make([]rPurchase.PurchaseReceivingUpdate, 0, len(prepared))
|
||||
fifoAdds := make([]struct {
|
||||
itemID uint
|
||||
pwID uint
|
||||
qty float64
|
||||
}, 0, len(prepared))
|
||||
|
||||
for _, prep := range prepared {
|
||||
item := prep.item
|
||||
@@ -811,21 +824,29 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation
|
||||
var newPWID *uint
|
||||
clearPW := false
|
||||
|
||||
// Always ensure PW when qty > 0 so stockable has target.
|
||||
if prep.receivedQty > 0 {
|
||||
pwID, err := pwRepoTx.EnsureProductWarehouse(c.Context(), uint(item.ProductId), prep.warehouseID, purchase.CreatedBy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newPWID = &pwID
|
||||
deltas[pwID] += prep.receivedQty
|
||||
affected[pwID] = struct{}{}
|
||||
} else {
|
||||
} else if oldPWID != nil {
|
||||
newPWID = oldPWID
|
||||
clearPW = true
|
||||
}
|
||||
|
||||
if oldPWID != nil {
|
||||
deltas[*oldPWID] -= item.TotalQty
|
||||
affected[*oldPWID] = struct{}{}
|
||||
deltaQty := prep.receivedQty - item.TotalQty
|
||||
switch {
|
||||
case deltaQty > 0 && newPWID != nil:
|
||||
fifoAdds = append(fifoAdds, struct {
|
||||
itemID uint
|
||||
pwID uint
|
||||
qty float64
|
||||
}{itemID: item.Id, pwID: *newPWID, qty: deltaQty})
|
||||
case deltaQty < 0 && newPWID != nil:
|
||||
deltas[*newPWID] += deltaQty // negative
|
||||
affected[*newPWID] = struct{}{}
|
||||
}
|
||||
|
||||
dateCopy := prep.receivedDate
|
||||
@@ -861,6 +882,23 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation
|
||||
return err
|
||||
}
|
||||
|
||||
if s.FifoSvc != nil {
|
||||
for _, adj := range fifoAdds {
|
||||
if adj.pwID == 0 || adj.qty <= 0 {
|
||||
continue
|
||||
}
|
||||
if _, err := s.FifoSvc.Replenish(c.Context(), commonSvc.StockReplenishRequest{
|
||||
StockableKey: purchaseStockableKey,
|
||||
StockableID: adj.itemID,
|
||||
ProductWarehouseID: adj.pwID,
|
||||
Quantity: adj.qty,
|
||||
Tx: tx,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if transactionErr != nil {
|
||||
|
||||
Reference in New Issue
Block a user