mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
update purchase triger to expense
This commit is contained in:
@@ -22,13 +22,11 @@ import (
|
||||
"gitlab.com/mbugroup/lti-api.git/internal/utils"
|
||||
)
|
||||
|
||||
// PurchaseExpenseBridge allows purchase flows to sync expense data on receiving/deletion.
|
||||
type PurchaseExpenseBridge interface {
|
||||
OnItemsDeleted(ctx context.Context, purchaseID uint, items []entity.PurchaseItem) error
|
||||
OnItemsReceived(c *fiber.Ctx, purchaseID uint, updates []ExpenseReceivingPayload) error
|
||||
}
|
||||
|
||||
// ExpenseReceivingPayload captures the minimum data expense integration will need once available.
|
||||
type ExpenseReceivingPayload struct {
|
||||
PurchaseItemID uint
|
||||
ProductID uint
|
||||
@@ -51,7 +49,6 @@ func groupingKey(supplierID uint, date time.Time, warehouseID uint) string {
|
||||
return fmt.Sprintf("%d:%s:%d", supplierID, utils.FormatDate(date), warehouseID)
|
||||
}
|
||||
|
||||
// expenseBridge is the real implementation that syncs purchases to expenses on receiving/deletion.
|
||||
type expenseBridge struct {
|
||||
db *gorm.DB
|
||||
purchaseRepo rPurchase.PurchaseRepository
|
||||
@@ -158,7 +155,6 @@ func (b *expenseBridge) OnItemsDeleted(ctx context.Context, _ uint, items []enti
|
||||
})
|
||||
}
|
||||
|
||||
// cleanupExistingNonstocks deletes expense_nonstocks (and their approvals/expenses if empty) for the given payloads.
|
||||
func (b *expenseBridge) cleanupExistingNonstocks(ctx context.Context, updates []ExpenseReceivingPayload) error {
|
||||
if len(updates) == 0 {
|
||||
return nil
|
||||
@@ -236,7 +232,6 @@ func (b *expenseBridge) cleanupExistingNonstocks(ctx context.Context, updates []
|
||||
})
|
||||
}
|
||||
|
||||
// cleanupEmptyExpenses deletes expense headers (and approvals) that have no nonstocks.
|
||||
func (b *expenseBridge) cleanupEmptyExpenses(ctx context.Context, expenseIDs []uint64) error {
|
||||
if len(expenseIDs) == 0 {
|
||||
return nil
|
||||
@@ -263,6 +258,23 @@ func (b *expenseBridge) cleanupEmptyExpenses(ctx context.Context, expenseIDs []u
|
||||
})
|
||||
}
|
||||
|
||||
func (b *expenseBridge) markExpensesUpdated(ctx context.Context, expenseIDs map[uint64]struct{}, actorID uint) error {
|
||||
if len(expenseIDs) == 0 {
|
||||
return nil
|
||||
}
|
||||
if actorID == 0 {
|
||||
actorID = 1
|
||||
}
|
||||
svc := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(b.db))
|
||||
action := entity.ApprovalActionUpdated
|
||||
for id := range expenseIDs {
|
||||
if _, err := svc.CreateApproval(ctx, utils.ApprovalWorkflowExpense, uint(id), utils.ExpenseStepFinance, &action, actorID, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *expenseBridge) OnItemsReceived(c *fiber.Ctx, purchaseID uint, updates []ExpenseReceivingPayload) error {
|
||||
if purchaseID == 0 || len(updates) == 0 {
|
||||
return nil
|
||||
@@ -292,6 +304,7 @@ func (b *expenseBridge) OnItemsReceived(c *fiber.Ctx, purchaseID uint, updates [
|
||||
|
||||
itemLinks := make(map[uint]itemLink)
|
||||
existingExpenseByKey := make(map[string]uint64)
|
||||
updatedExpenses := make(map[uint64]struct{})
|
||||
if len(updates) > 0 {
|
||||
ids := make([]uint, 0, len(updates))
|
||||
for _, upd := range updates {
|
||||
@@ -407,6 +420,7 @@ func (b *expenseBridge) OnItemsReceived(c *fiber.Ctx, purchaseID uint, updates [
|
||||
// Track cleanup for old header if it becomes empty.
|
||||
movedFrom = append(movedFrom, link.ExpenseID)
|
||||
existingExpenseByKey[newKey] = targetExpenseID
|
||||
updatedExpenses[targetExpenseID] = struct{}{}
|
||||
handledUpdate = true
|
||||
} else {
|
||||
requiresDelete = true
|
||||
@@ -426,6 +440,9 @@ func (b *expenseBridge) OnItemsReceived(c *fiber.Ctx, purchaseID uint, updates [
|
||||
}).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
if link.ExpenseID != 0 {
|
||||
updatedExpenses[link.ExpenseID] = struct{}{}
|
||||
}
|
||||
handledUpdate = true
|
||||
}
|
||||
}
|
||||
@@ -464,6 +481,9 @@ func (b *expenseBridge) OnItemsReceived(c *fiber.Ctx, purchaseID uint, updates [
|
||||
kandangID: kandangID,
|
||||
totalPrice: totalPrice,
|
||||
})
|
||||
if existingID, ok := existingExpenseByKey[key]; ok && existingID != 0 {
|
||||
updatedExpenses[existingID] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
// For payloads that require delete/recreate, clean up their old links first.
|
||||
@@ -541,6 +561,9 @@ func (b *expenseBridge) OnItemsReceived(c *fiber.Ctx, purchaseID uint, updates [
|
||||
if err := b.linkExpenseNonstocksToItems(ctx, expenseDetail, items); err != nil {
|
||||
return err
|
||||
}
|
||||
if expenseDetail != nil && expenseDetail.Id != 0 {
|
||||
updatedExpenses[uint64(expenseDetail.Id)] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
// Cleanup old expense headers that became empty after re-link.
|
||||
@@ -550,6 +573,12 @@ func (b *expenseBridge) OnItemsReceived(c *fiber.Ctx, purchaseID uint, updates [
|
||||
}
|
||||
}
|
||||
|
||||
if len(updatedExpenses) > 0 {
|
||||
if err := b.markExpensesUpdated(ctx, updatedExpenses, purchase.CreatedBy); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -996,10 +996,8 @@ func (s *purchaseService) DeletePurchase(c *fiber.Ctx, id uint) error {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to get purchase")
|
||||
}
|
||||
|
||||
itemIDs := make([]uint, 0, len(purchase.Items))
|
||||
itemsToDelete := make([]entity.PurchaseItem, len(purchase.Items))
|
||||
for i, item := range purchase.Items {
|
||||
itemIDs = append(itemIDs, item.Id)
|
||||
itemsToDelete[i] = item
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user