mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
fix: first push need support testing, and implemented fifo v2 to all modules
This commit is contained in:
@@ -57,7 +57,7 @@ type purchaseService struct {
|
||||
ProjectFlockKandangRepo projectFlockKandangRepo.ProjectFlockKandangRepository
|
||||
ApprovalSvc commonSvc.ApprovalService
|
||||
ExpenseBridge PurchaseExpenseBridge
|
||||
FifoSvc commonSvc.FifoService
|
||||
FifoStockV2Svc commonSvc.FifoStockV2Service
|
||||
DocumentSvc commonSvc.DocumentService
|
||||
approvalWorkflow approvalutils.ApprovalWorkflowKey
|
||||
}
|
||||
@@ -77,7 +77,7 @@ func NewPurchaseService(
|
||||
projectFlockKandangRepo projectFlockKandangRepo.ProjectFlockKandangRepository,
|
||||
approvalSvc commonSvc.ApprovalService,
|
||||
expenseBridge PurchaseExpenseBridge,
|
||||
fifoSvc commonSvc.FifoService,
|
||||
fifoStockV2Svc commonSvc.FifoStockV2Service,
|
||||
documentSvc commonSvc.DocumentService,
|
||||
) PurchaseService {
|
||||
return &purchaseService{
|
||||
@@ -91,7 +91,7 @@ func NewPurchaseService(
|
||||
ProjectFlockKandangRepo: projectFlockKandangRepo,
|
||||
ApprovalSvc: approvalSvc,
|
||||
ExpenseBridge: expenseBridge,
|
||||
FifoSvc: fifoSvc,
|
||||
FifoStockV2Svc: fifoStockV2Svc,
|
||||
DocumentSvc: documentSvc,
|
||||
approvalWorkflow: utils.ApprovalWorkflowPurchase,
|
||||
}
|
||||
@@ -1026,22 +1026,11 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation
|
||||
pwRepoTx := rProductWarehouse.NewProductWarehouseRepository(tx)
|
||||
stockLogRepoTx := rStockLogs.NewStockLogRepository(tx)
|
||||
|
||||
deltas := make(map[uint]float64)
|
||||
affected := make(map[uint]struct{})
|
||||
updates := make([]rPurchase.PurchaseReceivingUpdate, 0, len(prepared))
|
||||
priceUpdates := make([]rPurchase.PurchasePricingUpdate, 0, len(prepared))
|
||||
totalQtyDeltas := make(map[uint]float64)
|
||||
fifoAdds := make([]struct {
|
||||
itemID uint
|
||||
pwID uint
|
||||
qty float64
|
||||
}, 0, len(prepared))
|
||||
fifoSubs := make([]struct {
|
||||
itemID uint
|
||||
pwID uint
|
||||
qty float64
|
||||
}, 0, len(prepared))
|
||||
resolvePendingIDs := make(map[uint]struct{})
|
||||
reflowAsOfByPW := make(map[uint]time.Time)
|
||||
logEntries := make([]struct {
|
||||
itemID uint
|
||||
pwID uint
|
||||
@@ -1083,35 +1072,14 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation
|
||||
delta float64
|
||||
}{itemID: item.Id, pwID: *newPWID, delta: deltaQty})
|
||||
}
|
||||
switch {
|
||||
case deltaQty > 0 && newPWID != nil:
|
||||
if s.FifoSvc != nil {
|
||||
fifoAdds = append(fifoAdds, struct {
|
||||
itemID uint
|
||||
pwID uint
|
||||
qty float64
|
||||
}{itemID: item.Id, pwID: *newPWID, qty: deltaQty})
|
||||
resolvePendingIDs[*newPWID] = struct{}{}
|
||||
} else {
|
||||
deltas[*newPWID] += deltaQty
|
||||
totalQtyDeltas[item.Id] += deltaQty
|
||||
}
|
||||
case deltaQty < 0 && newPWID != nil:
|
||||
if s.FifoSvc != nil {
|
||||
fifoSubs = append(fifoSubs, struct {
|
||||
itemID uint
|
||||
pwID uint
|
||||
qty float64
|
||||
}{itemID: item.Id, pwID: *newPWID, qty: deltaQty})
|
||||
affected[*newPWID] = struct{}{}
|
||||
resolvePendingIDs[*newPWID] = struct{}{}
|
||||
} else {
|
||||
deltas[*newPWID] += deltaQty // negative
|
||||
affected[*newPWID] = struct{}{}
|
||||
totalQtyDeltas[item.Id] += deltaQty
|
||||
}
|
||||
case newPWID != nil:
|
||||
resolvePendingIDs[*newPWID] = struct{}{}
|
||||
if newPWID != nil {
|
||||
assignEarliestAsOf(reflowAsOfByPW, *newPWID, prep.receivedDate.UTC())
|
||||
}
|
||||
if deltaQty != 0 {
|
||||
totalQtyDeltas[item.Id] += deltaQty
|
||||
}
|
||||
if deltaQty < 0 && newPWID != nil {
|
||||
affected[*newPWID] = struct{}{}
|
||||
}
|
||||
|
||||
dateCopy := prep.receivedDate
|
||||
@@ -1147,10 +1115,6 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation
|
||||
return err
|
||||
}
|
||||
|
||||
if err := pwRepoTx.AdjustQuantities(c.Context(), deltas, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(priceUpdates) > 0 {
|
||||
if err := repoTx.UpdatePricing(c.Context(), purchase.Id, priceUpdates); err != nil {
|
||||
return err
|
||||
@@ -1180,48 +1144,16 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation
|
||||
}
|
||||
}
|
||||
|
||||
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: fifo.StockableKeyPurchaseItems,
|
||||
StockableID: adj.itemID,
|
||||
ProductWarehouseID: adj.pwID,
|
||||
Quantity: adj.qty,
|
||||
Tx: tx,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(reflowAsOfByPW) > 0 {
|
||||
if s.FifoStockV2Svc == nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "FIFO v2 service is not available")
|
||||
}
|
||||
for _, adj := range fifoSubs {
|
||||
if adj.pwID == 0 || adj.qty >= 0 {
|
||||
continue
|
||||
}
|
||||
if err := s.FifoSvc.AdjustStockableQuantity(c.Context(), commonSvc.StockAdjustRequest{
|
||||
StockableKey: fifo.StockableKeyPurchaseItems,
|
||||
StockableID: adj.itemID,
|
||||
ProductWarehouseID: adj.pwID,
|
||||
Quantity: adj.qty,
|
||||
Tx: tx,
|
||||
}); err != nil {
|
||||
for pwID, asOf := range reflowAsOfByPW {
|
||||
asOfCopy := asOf
|
||||
if err := reflowPurchaseScope(c.Context(), s.FifoStockV2Svc, tx, pwID, &asOfCopy); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
for pwID := range resolvePendingIDs {
|
||||
if pwID == 0 {
|
||||
continue
|
||||
}
|
||||
resolved, err := s.FifoSvc.ResolvePending(c.Context(), commonSvc.PendingResolveRequest{
|
||||
ProductWarehouseID: pwID,
|
||||
Tx: tx,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s.Log.Infof("ResolvePending purchase=%d pw=%d resolved=%d", purchase.Id, pwID, len(resolved))
|
||||
}
|
||||
}
|
||||
|
||||
if len(logEntries) > 0 {
|
||||
@@ -1577,10 +1509,9 @@ func (s *purchaseService) rollbackPurchaseStock(ctx context.Context, tx *gorm.DB
|
||||
return nil
|
||||
}
|
||||
|
||||
pwRepoTx := rProductWarehouse.NewProductWarehouseRepository(tx)
|
||||
stockLogRepoTx := rStockLogs.NewStockLogRepository(tx)
|
||||
deltas := make(map[uint]float64)
|
||||
affected := make(map[uint]struct{})
|
||||
reflowAsOfByPW := make(map[uint]time.Time)
|
||||
logEntries := make([]struct {
|
||||
pwID uint
|
||||
qty float64
|
||||
@@ -1596,42 +1527,43 @@ func (s *purchaseService) rollbackPurchaseStock(ctx context.Context, tx *gorm.DB
|
||||
pwID := *item.ProductWarehouseId
|
||||
qty := item.TotalQty
|
||||
|
||||
if s.FifoSvc != nil {
|
||||
if err := s.FifoSvc.AdjustStockableQuantity(ctx, commonSvc.StockAdjustRequest{
|
||||
StockableKey: fifo.StockableKeyPurchaseItems,
|
||||
StockableID: item.Id,
|
||||
ProductWarehouseID: pwID,
|
||||
Quantity: -qty,
|
||||
Tx: tx,
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
logEntries = append(logEntries, struct {
|
||||
pwID uint
|
||||
qty float64
|
||||
}{pwID: pwID, qty: qty})
|
||||
continue
|
||||
if err := tx.WithContext(ctx).
|
||||
Model(&entity.PurchaseItem{}).
|
||||
Where("id = ?", item.Id).
|
||||
Update("total_qty", 0).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
deltas[pwID] -= qty
|
||||
affected[pwID] = struct{}{}
|
||||
if item.ReceivedDate != nil {
|
||||
assignEarliestAsOf(reflowAsOfByPW, pwID, item.ReceivedDate.UTC())
|
||||
} else {
|
||||
assignEarliestAsOf(reflowAsOfByPW, pwID, time.Now().UTC())
|
||||
}
|
||||
logEntries = append(logEntries, struct {
|
||||
pwID uint
|
||||
qty float64
|
||||
}{pwID: pwID, qty: qty})
|
||||
}
|
||||
|
||||
if s.FifoSvc == nil && len(deltas) > 0 {
|
||||
if err := pwRepoTx.AdjustQuantities(ctx, deltas, nil); err != nil {
|
||||
return err
|
||||
if len(reflowAsOfByPW) > 0 {
|
||||
if s.FifoStockV2Svc == nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "FIFO v2 service is not available")
|
||||
}
|
||||
if len(affected) > 0 {
|
||||
if err := pwRepoTx.CleanupEmpty(ctx, affected); err != nil {
|
||||
for pwID, asOf := range reflowAsOfByPW {
|
||||
asOfCopy := asOf
|
||||
if err := reflowPurchaseScope(ctx, s.FifoStockV2Svc, tx, pwID, &asOfCopy); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(affected) > 0 {
|
||||
if err := rProductWarehouse.NewProductWarehouseRepository(tx).CleanupEmpty(ctx, affected); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if strings.TrimSpace(note) != "" && actorID != 0 && len(logEntries) > 0 {
|
||||
logs := make([]*entity.StockLog, 0, len(logEntries))
|
||||
for _, entry := range logEntries {
|
||||
|
||||
Reference in New Issue
Block a user