From a6995f8e1857dc328604f27619744104c2fe6259 Mon Sep 17 00:00:00 2001 From: giovanni Date: Wed, 8 Apr 2026 16:18:55 +0700 Subject: [PATCH] fix edit receipt purchase --- .../repositories/purchase.repository.go | 3 + .../purchases/services/expense_bridge.go | 92 +++++++++++++++++++ .../purchases/services/purchase.service.go | 19 ++-- 3 files changed, 108 insertions(+), 6 deletions(-) diff --git a/internal/modules/purchases/repositories/purchase.repository.go b/internal/modules/purchases/repositories/purchase.repository.go index 56e6b8c6..2f5818c4 100644 --- a/internal/modules/purchases/repositories/purchase.repository.go +++ b/internal/modules/purchases/repositories/purchase.repository.go @@ -169,6 +169,7 @@ type PurchaseReceivingUpdate struct { TravelNumber *string TravelDocumentPath *string VehicleNumber *string + ClearVehicleNumber bool ReceivedQty *float64 WarehouseID *uint ProductWarehouseID *uint @@ -246,6 +247,8 @@ func (r *PurchaseRepositoryImpl) UpdateReceivingDetails( } if upd.VehicleNumber != nil { data["vehicle_number"] = upd.VehicleNumber + } else if upd.ClearVehicleNumber { + data["vehicle_number"] = gorm.Expr("NULL") } if upd.WarehouseID != nil && *upd.WarehouseID != 0 { data["warehouse_id"] = upd.WarehouseID diff --git a/internal/modules/purchases/services/expense_bridge.go b/internal/modules/purchases/services/expense_bridge.go index d3bf2bbf..ec6c51d2 100644 --- a/internal/modules/purchases/services/expense_bridge.go +++ b/internal/modules/purchases/services/expense_bridge.go @@ -183,15 +183,102 @@ func (b *expenseBridge) markExpensesUpdated(ctx context.Context, expenseIDs map[ return nil } +func (b *expenseBridge) clearExpenseLinksForItems(ctx context.Context, itemIDs []uint) error { + if len(itemIDs) == 0 { + return nil + } + + unique := make(map[uint]struct{}, len(itemIDs)) + normalized := make([]uint, 0, len(itemIDs)) + for _, id := range itemIDs { + if id == 0 { + continue + } + if _, exists := unique[id]; exists { + continue + } + unique[id] = struct{}{} + normalized = append(normalized, id) + } + if len(normalized) == 0 { + return nil + } + + rows := make([]struct { + ItemID uint + ExpenseNonstockID *uint64 + ExpenseID *uint64 + }, 0, len(normalized)) + if err := b.db.WithContext(ctx). + Table("purchase_items pi"). + Select("pi.id as item_id, pi.expense_nonstock_id, en.expense_id"). + Joins("LEFT JOIN expense_nonstocks en ON en.id = pi.expense_nonstock_id"). + Where("pi.id IN ?", normalized). + Scan(&rows).Error; err != nil { + return err + } + + expenseNonstockIDs := make([]uint64, 0, len(rows)) + expenseIDs := make(map[uint64]struct{}) + for _, row := range rows { + if row.ExpenseNonstockID != nil && *row.ExpenseNonstockID != 0 { + expenseNonstockIDs = append(expenseNonstockIDs, *row.ExpenseNonstockID) + } + if row.ExpenseID != nil && *row.ExpenseID != 0 { + expenseIDs[*row.ExpenseID] = struct{}{} + } + } + + return b.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error { + if err := tx.Model(&entity.PurchaseItem{}). + Where("id IN ?", normalized). + Update("expense_nonstock_id", gorm.Expr("NULL")).Error; err != nil { + return err + } + + if len(expenseNonstockIDs) > 0 { + if err := tx.Where("id IN ?", expenseNonstockIDs).Delete(&entity.ExpenseNonstock{}).Error; err != nil { + return err + } + } + + approvalRepoTx := commonRepo.NewApprovalRepository(tx) + for expenseID := range expenseIDs { + var count int64 + if err := tx.Model(&entity.ExpenseNonstock{}). + Where("expense_id = ?", expenseID). + Count(&count).Error; err != nil { + return err + } + if count > 0 { + continue + } + + if err := approvalRepoTx.DeleteByTarget(ctx, utils.ApprovalWorkflowExpense.String(), uint(expenseID)); err != nil { + return err + } + if err := tx.Delete(&entity.Expense{}, expenseID).Error; 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 } ctx := c.Context() + clearExpenseLinks := make([]uint, 0, len(updates)) filtered := make([]ExpenseReceivingPayload, 0, len(updates)) for _, upd := range updates { + if upd.PurchaseItemID == 0 { + continue + } if upd.SupplierID == 0 { + clearExpenseLinks = append(clearExpenseLinks, upd.PurchaseItemID) continue } if upd.TransportPerItem == nil || *upd.TransportPerItem <= 0 { @@ -202,6 +289,11 @@ func (b *expenseBridge) OnItemsReceived(c *fiber.Ctx, purchaseID uint, updates [ } filtered = append(filtered, upd) } + if len(clearExpenseLinks) > 0 { + if err := b.clearExpenseLinksForItems(ctx, clearExpenseLinks); err != nil { + return err + } + } if len(filtered) == 0 { return nil } diff --git a/internal/modules/purchases/services/purchase.service.go b/internal/modules/purchases/services/purchase.service.go index a48e103d..bd2f9f0d 100644 --- a/internal/modules/purchases/services/purchase.service.go +++ b/internal/modules/purchases/services/purchase.service.go @@ -949,6 +949,7 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation supplierID uint transportPerItem *float64 vehicleNumber *string + clearVehicle bool overrideWarehouse bool receivedQty float64 } @@ -1041,12 +1042,16 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation } var vehicleNumber *string - if payload.VehicleNumber != nil && strings.TrimSpace(*payload.VehicleNumber) != "" { + clearVehicle := false + if payload.VehicleNumber != nil { val := strings.TrimSpace(*payload.VehicleNumber) - vehicleNumber = &val - } else if item.VehicleNumber != nil && strings.TrimSpace(*item.VehicleNumber) != "" { - val := strings.TrimSpace(*item.VehicleNumber) - vehicleNumber = &val + if val != "" { + vehicleNumber = &val + } else { + clearVehicle = true + } + } else { + clearVehicle = true } prepared = append(prepared, preparedReceiving{ @@ -1057,6 +1062,7 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation supplierID: supplierID, transportPerItem: transportPerItem, vehicleNumber: vehicleNumber, + clearVehicle: clearVehicle, overrideWarehouse: overrideWarehouse, receivedQty: receivedQty, }) @@ -1170,7 +1176,8 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation ReceivedDate: &dateCopy, TravelNumber: prep.payload.TravelNumber, TravelDocumentPath: prep.payload.TravelDocumentPath, - VehicleNumber: prep.payload.VehicleNumber, + VehicleNumber: prep.vehicleNumber, + ClearVehicleNumber: prep.clearVehicle, ReceivedQty: &qtyCopy, ProductWarehouseID: newPWID, ClearProductWarehouse: false,