mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +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",
|
ProductWarehouseID: "product_warehouse_id",
|
||||||
UsageQuantity: "usage_qty",
|
UsageQuantity: "usage_qty",
|
||||||
PendingQuantity: "pending_qty",
|
PendingQuantity: "pending_qty",
|
||||||
CreatedAt: "created_at",
|
CreatedAt: "id",
|
||||||
},
|
},
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
if !strings.Contains(strings.ToLower(err.Error()), "already registered") {
|
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"
|
rUser "gitlab.com/mbugroup/lti-api.git/internal/modules/users/repositories"
|
||||||
sUser "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
|
sUser "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
|
||||||
utils "gitlab.com/mbugroup/lti-api.git/internal/utils"
|
utils "gitlab.com/mbugroup/lti-api.git/internal/utils"
|
||||||
|
"gitlab.com/mbugroup/lti-api.git/internal/utils/fifo"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -36,6 +37,7 @@ func (PurchaseModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validate
|
|||||||
expenseRepository := expenseRepo.NewExpenseRepository(db)
|
expenseRepository := expenseRepo.NewExpenseRepository(db)
|
||||||
expenseRealizationRepo := expenseRepo.NewExpenseRealizationRepository(db)
|
expenseRealizationRepo := expenseRepo.NewExpenseRealizationRepository(db)
|
||||||
projectFlockKandangRepository := projectFlockKandangRepo.NewProjectFlockKandangRepository(db)
|
projectFlockKandangRepository := projectFlockKandangRepo.NewProjectFlockKandangRepository(db)
|
||||||
|
stockAllocRepo := commonRepo.NewStockAllocationRepository(db)
|
||||||
|
|
||||||
approvalRepo := commonRepo.NewApprovalRepository(db)
|
approvalRepo := commonRepo.NewApprovalRepository(db)
|
||||||
approvalService := commonSvc.NewApprovalService(approvalRepo)
|
approvalService := commonSvc.NewApprovalService(approvalRepo)
|
||||||
@@ -61,6 +63,20 @@ func (PurchaseModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validate
|
|||||||
expenseServiceInstance,
|
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(
|
purchaseService := service.NewPurchaseService(
|
||||||
validate,
|
validate,
|
||||||
purchaseRepo,
|
purchaseRepo,
|
||||||
@@ -71,6 +87,7 @@ func (PurchaseModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validate
|
|||||||
projectFlockKandangRepository,
|
projectFlockKandangRepository,
|
||||||
approvalService,
|
approvalService,
|
||||||
expenseBridge,
|
expenseBridge,
|
||||||
|
fifoService,
|
||||||
)
|
)
|
||||||
|
|
||||||
userRepo := rUser.NewUserRepository(db)
|
userRepo := rUser.NewUserRepository(db)
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import (
|
|||||||
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/purchases/validations"
|
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/purchases/validations"
|
||||||
"gitlab.com/mbugroup/lti-api.git/internal/utils"
|
"gitlab.com/mbugroup/lti-api.git/internal/utils"
|
||||||
approvalutils "gitlab.com/mbugroup/lti-api.git/internal/utils/approvals"
|
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/go-playground/validator/v10"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
@@ -40,7 +41,8 @@ type PurchaseService interface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
priceTolerance = 0.0001
|
priceTolerance = 0.0001
|
||||||
|
purchaseStockableKey = fifo.StockableKey("PURCHASE_ITEMS")
|
||||||
)
|
)
|
||||||
|
|
||||||
type purchaseService struct {
|
type purchaseService struct {
|
||||||
@@ -54,6 +56,7 @@ type purchaseService struct {
|
|||||||
ProjectFlockKandangRepo projectFlockKandangRepo.ProjectFlockKandangRepository
|
ProjectFlockKandangRepo projectFlockKandangRepo.ProjectFlockKandangRepository
|
||||||
ApprovalSvc commonSvc.ApprovalService
|
ApprovalSvc commonSvc.ApprovalService
|
||||||
ExpenseBridge PurchaseExpenseBridge
|
ExpenseBridge PurchaseExpenseBridge
|
||||||
|
FifoSvc commonSvc.FifoService
|
||||||
approvalWorkflow approvalutils.ApprovalWorkflowKey
|
approvalWorkflow approvalutils.ApprovalWorkflowKey
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,6 +75,7 @@ func NewPurchaseService(
|
|||||||
projectFlockKandangRepo projectFlockKandangRepo.ProjectFlockKandangRepository,
|
projectFlockKandangRepo projectFlockKandangRepo.ProjectFlockKandangRepository,
|
||||||
approvalSvc commonSvc.ApprovalService,
|
approvalSvc commonSvc.ApprovalService,
|
||||||
expenseBridge PurchaseExpenseBridge,
|
expenseBridge PurchaseExpenseBridge,
|
||||||
|
fifoSvc commonSvc.FifoService,
|
||||||
) PurchaseService {
|
) PurchaseService {
|
||||||
return &purchaseService{
|
return &purchaseService{
|
||||||
Log: utils.Log,
|
Log: utils.Log,
|
||||||
@@ -84,6 +88,7 @@ func NewPurchaseService(
|
|||||||
ProjectFlockKandangRepo: projectFlockKandangRepo,
|
ProjectFlockKandangRepo: projectFlockKandangRepo,
|
||||||
ApprovalSvc: approvalSvc,
|
ApprovalSvc: approvalSvc,
|
||||||
ExpenseBridge: expenseBridge,
|
ExpenseBridge: expenseBridge,
|
||||||
|
FifoSvc: fifoSvc,
|
||||||
approvalWorkflow: utils.ApprovalWorkflowPurchase,
|
approvalWorkflow: utils.ApprovalWorkflowPurchase,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -712,6 +717,9 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation
|
|||||||
if warehouseID == 0 {
|
if warehouseID == 0 {
|
||||||
return nil, fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Warehouse must be specified for item %d", payload.PurchaseItemID))
|
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
|
var receivedQty float64
|
||||||
if payload.ReceivedQty != nil {
|
if payload.ReceivedQty != nil {
|
||||||
@@ -798,6 +806,11 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation
|
|||||||
deltas := make(map[uint]float64)
|
deltas := make(map[uint]float64)
|
||||||
affected := make(map[uint]struct{})
|
affected := make(map[uint]struct{})
|
||||||
updates := make([]rPurchase.PurchaseReceivingUpdate, 0, len(prepared))
|
updates := make([]rPurchase.PurchaseReceivingUpdate, 0, len(prepared))
|
||||||
|
fifoAdds := make([]struct {
|
||||||
|
itemID uint
|
||||||
|
pwID uint
|
||||||
|
qty float64
|
||||||
|
}, 0, len(prepared))
|
||||||
|
|
||||||
for _, prep := range prepared {
|
for _, prep := range prepared {
|
||||||
item := prep.item
|
item := prep.item
|
||||||
@@ -811,21 +824,29 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation
|
|||||||
var newPWID *uint
|
var newPWID *uint
|
||||||
clearPW := false
|
clearPW := false
|
||||||
|
|
||||||
|
// Always ensure PW when qty > 0 so stockable has target.
|
||||||
if prep.receivedQty > 0 {
|
if prep.receivedQty > 0 {
|
||||||
pwID, err := pwRepoTx.EnsureProductWarehouse(c.Context(), uint(item.ProductId), prep.warehouseID, purchase.CreatedBy)
|
pwID, err := pwRepoTx.EnsureProductWarehouse(c.Context(), uint(item.ProductId), prep.warehouseID, purchase.CreatedBy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
newPWID = &pwID
|
newPWID = &pwID
|
||||||
deltas[pwID] += prep.receivedQty
|
} else if oldPWID != nil {
|
||||||
affected[pwID] = struct{}{}
|
newPWID = oldPWID
|
||||||
} else {
|
|
||||||
clearPW = true
|
clearPW = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if oldPWID != nil {
|
deltaQty := prep.receivedQty - item.TotalQty
|
||||||
deltas[*oldPWID] -= item.TotalQty
|
switch {
|
||||||
affected[*oldPWID] = struct{}{}
|
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
|
dateCopy := prep.receivedDate
|
||||||
@@ -861,6 +882,23 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation
|
|||||||
return err
|
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
|
return nil
|
||||||
})
|
})
|
||||||
if transactionErr != nil {
|
if transactionErr != nil {
|
||||||
|
|||||||
Reference in New Issue
Block a user