mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
Merge branch 'fix/BE/Purchase-edit-qty' into 'development'
[FIX/BE-US] fixing stock log delete recording and purchase See merge request mbugroup/lti-api!267
This commit is contained in:
@@ -711,6 +711,11 @@ func (s recordingService) Approval(c *fiber.Ctx, req *validation.Approve) ([]ent
|
||||
|
||||
func (s recordingService) DeleteOne(c *fiber.Ctx, id uint) error {
|
||||
ctx := c.Context()
|
||||
actorID, err := m.ActorIDFromContext(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
note := fmt.Sprintf("Recording-Delete#%d", id)
|
||||
|
||||
return s.Repository.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
oldDepletions, err := s.Repository.ListDepletions(tx, id)
|
||||
@@ -719,7 +724,7 @@ func (s recordingService) DeleteOne(c *fiber.Ctx, id uint) error {
|
||||
return err
|
||||
}
|
||||
if s.FifoSvc != nil {
|
||||
if err := s.releaseRecordingDepletions(ctx, tx, oldDepletions, "", 0); err != nil {
|
||||
if err := s.releaseRecordingDepletions(ctx, tx, oldDepletions, note, actorID); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -741,7 +746,7 @@ func (s recordingService) DeleteOne(c *fiber.Ctx, id uint) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.releaseRecordingStocks(ctx, tx, oldStocks, "", 0); err != nil {
|
||||
if err := s.releaseRecordingStocks(ctx, tx, oldStocks, note, actorID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -749,6 +754,10 @@ func (s recordingService) DeleteOne(c *fiber.Ctx, id uint) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.logRecordingEggRollback(ctx, tx, oldEggs, note, actorID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.Repository.WithTx(tx).DeleteOne(ctx, id); err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return fiber.NewError(fiber.StatusNotFound, "Recording not found")
|
||||
@@ -761,6 +770,40 @@ func (s recordingService) DeleteOne(c *fiber.Ctx, id uint) error {
|
||||
})
|
||||
}
|
||||
|
||||
func (s *recordingService) logRecordingEggRollback(
|
||||
ctx context.Context,
|
||||
tx *gorm.DB,
|
||||
eggs []entity.RecordingEgg,
|
||||
note string,
|
||||
actorID uint,
|
||||
) error {
|
||||
if len(eggs) == 0 || s.StockLogRepo == nil {
|
||||
return nil
|
||||
}
|
||||
if strings.TrimSpace(note) == "" || actorID == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, egg := range eggs {
|
||||
if egg.ProductWarehouseId == 0 || egg.Qty <= 0 {
|
||||
continue
|
||||
}
|
||||
log := &entity.StockLog{
|
||||
ProductWarehouseId: egg.ProductWarehouseId,
|
||||
CreatedBy: actorID,
|
||||
Decrease: float64(egg.Qty),
|
||||
LoggableType: string(utils.StockLogTypeRecording),
|
||||
LoggableId: egg.RecordingId,
|
||||
Notes: note,
|
||||
}
|
||||
if err := s.StockLogRepo.WithTx(tx).CreateOne(ctx, log, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// === Persistence Helpers ===
|
||||
|
||||
func (s *recordingService) ensureProductWarehousesExist(c *fiber.Ctx, stocks []validation.Stock, depletions []validation.Depletion, eggs []validation.Egg) error {
|
||||
|
||||
@@ -18,9 +18,9 @@ import (
|
||||
rSupplier "gitlab.com/mbugroup/lti-api.git/internal/modules/master/suppliers/repositories"
|
||||
rWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/repositories"
|
||||
projectFlockKandangRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories"
|
||||
rStockLogs "gitlab.com/mbugroup/lti-api.git/internal/modules/shared/repositories"
|
||||
rPurchase "gitlab.com/mbugroup/lti-api.git/internal/modules/purchases/repositories"
|
||||
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/purchases/validations"
|
||||
rStockLogs "gitlab.com/mbugroup/lti-api.git/internal/modules/shared/repositories"
|
||||
"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"
|
||||
@@ -1256,6 +1256,10 @@ func (s *purchaseService) DeletePurchase(c *fiber.Ctx, id uint) error {
|
||||
}
|
||||
|
||||
ctx := c.Context()
|
||||
actorID, err := m.ActorIDFromContext(c)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
purchase, err := s.loadPurchase(ctx, id)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -1269,7 +1273,16 @@ func (s *purchaseService) DeletePurchase(c *fiber.Ctx, id uint) error {
|
||||
itemsToDelete[i] = item
|
||||
}
|
||||
|
||||
note := fmt.Sprintf("Purchase-Delete#%d", purchase.Id)
|
||||
if purchase.PoNumber != nil && strings.TrimSpace(*purchase.PoNumber) != "" {
|
||||
note = fmt.Sprintf("%s#delete", strings.TrimSpace(*purchase.PoNumber))
|
||||
}
|
||||
|
||||
transactionErr := s.PurchaseRepo.DB().WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
if err := s.rollbackPurchaseStock(ctx, tx, itemsToDelete, note, actorID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
approvalRepoTx := commonRepo.NewApprovalRepository(tx)
|
||||
if err := approvalRepoTx.DeleteByTarget(ctx, utils.ApprovalWorkflowPurchase.String(), uint(id)); err != nil {
|
||||
return err
|
||||
@@ -1305,6 +1318,91 @@ func (s *purchaseService) DeletePurchase(c *fiber.Ctx, id uint) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *purchaseService) rollbackPurchaseStock(ctx context.Context, tx *gorm.DB, items []entity.PurchaseItem, note string, actorID uint) error {
|
||||
if len(items) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
pwRepoTx := rProductWarehouse.NewProductWarehouseRepository(tx)
|
||||
stockLogRepoTx := rStockLogs.NewStockLogRepository(tx)
|
||||
deltas := make(map[uint]float64)
|
||||
affected := make(map[uint]struct{})
|
||||
logEntries := make([]struct {
|
||||
pwID uint
|
||||
qty float64
|
||||
}, 0, len(items))
|
||||
|
||||
for _, item := range items {
|
||||
if item.ProductWarehouseId == nil || *item.ProductWarehouseId == 0 {
|
||||
continue
|
||||
}
|
||||
if item.TotalQty == 0 {
|
||||
continue
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
deltas[pwID] -= qty
|
||||
affected[pwID] = struct{}{}
|
||||
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(affected) > 0 {
|
||||
if err := pwRepoTx.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 {
|
||||
if entry.pwID == 0 || entry.qty <= 0 {
|
||||
continue
|
||||
}
|
||||
logs = append(logs, &entity.StockLog{
|
||||
ProductWarehouseId: entry.pwID,
|
||||
CreatedBy: actorID,
|
||||
Decrease: entry.qty,
|
||||
LoggableType: string(utils.StockLogTypePurchase),
|
||||
LoggableId: items[0].PurchaseId,
|
||||
Notes: note,
|
||||
})
|
||||
}
|
||||
if len(logs) > 0 {
|
||||
if err := stockLogRepoTx.CreateMany(ctx, logs, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *purchaseService) createPurchaseApproval(
|
||||
ctx context.Context,
|
||||
db *gorm.DB,
|
||||
|
||||
Reference in New Issue
Block a user