fix edit receipt purchase

This commit is contained in:
giovanni
2026-04-08 16:18:55 +07:00
parent 079ae01b94
commit a6995f8e18
3 changed files with 108 additions and 6 deletions
@@ -169,6 +169,7 @@ type PurchaseReceivingUpdate struct {
TravelNumber *string TravelNumber *string
TravelDocumentPath *string TravelDocumentPath *string
VehicleNumber *string VehicleNumber *string
ClearVehicleNumber bool
ReceivedQty *float64 ReceivedQty *float64
WarehouseID *uint WarehouseID *uint
ProductWarehouseID *uint ProductWarehouseID *uint
@@ -246,6 +247,8 @@ func (r *PurchaseRepositoryImpl) UpdateReceivingDetails(
} }
if upd.VehicleNumber != nil { if upd.VehicleNumber != nil {
data["vehicle_number"] = upd.VehicleNumber data["vehicle_number"] = upd.VehicleNumber
} else if upd.ClearVehicleNumber {
data["vehicle_number"] = gorm.Expr("NULL")
} }
if upd.WarehouseID != nil && *upd.WarehouseID != 0 { if upd.WarehouseID != nil && *upd.WarehouseID != 0 {
data["warehouse_id"] = upd.WarehouseID data["warehouse_id"] = upd.WarehouseID
@@ -183,15 +183,102 @@ func (b *expenseBridge) markExpensesUpdated(ctx context.Context, expenseIDs map[
return nil 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 { func (b *expenseBridge) OnItemsReceived(c *fiber.Ctx, purchaseID uint, updates []ExpenseReceivingPayload) error {
if purchaseID == 0 || len(updates) == 0 { if purchaseID == 0 || len(updates) == 0 {
return nil return nil
} }
ctx := c.Context() ctx := c.Context()
clearExpenseLinks := make([]uint, 0, len(updates))
filtered := make([]ExpenseReceivingPayload, 0, len(updates)) filtered := make([]ExpenseReceivingPayload, 0, len(updates))
for _, upd := range updates { for _, upd := range updates {
if upd.PurchaseItemID == 0 {
continue
}
if upd.SupplierID == 0 { if upd.SupplierID == 0 {
clearExpenseLinks = append(clearExpenseLinks, upd.PurchaseItemID)
continue continue
} }
if upd.TransportPerItem == nil || *upd.TransportPerItem <= 0 { 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) filtered = append(filtered, upd)
} }
if len(clearExpenseLinks) > 0 {
if err := b.clearExpenseLinksForItems(ctx, clearExpenseLinks); err != nil {
return err
}
}
if len(filtered) == 0 { if len(filtered) == 0 {
return nil return nil
} }
@@ -949,6 +949,7 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation
supplierID uint supplierID uint
transportPerItem *float64 transportPerItem *float64
vehicleNumber *string vehicleNumber *string
clearVehicle bool
overrideWarehouse bool overrideWarehouse bool
receivedQty float64 receivedQty float64
} }
@@ -1041,12 +1042,16 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation
} }
var vehicleNumber *string var vehicleNumber *string
if payload.VehicleNumber != nil && strings.TrimSpace(*payload.VehicleNumber) != "" { clearVehicle := false
if payload.VehicleNumber != nil {
val := strings.TrimSpace(*payload.VehicleNumber) val := strings.TrimSpace(*payload.VehicleNumber)
vehicleNumber = &val if val != "" {
} else if item.VehicleNumber != nil && strings.TrimSpace(*item.VehicleNumber) != "" { vehicleNumber = &val
val := strings.TrimSpace(*item.VehicleNumber) } else {
vehicleNumber = &val clearVehicle = true
}
} else {
clearVehicle = true
} }
prepared = append(prepared, preparedReceiving{ prepared = append(prepared, preparedReceiving{
@@ -1057,6 +1062,7 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation
supplierID: supplierID, supplierID: supplierID,
transportPerItem: transportPerItem, transportPerItem: transportPerItem,
vehicleNumber: vehicleNumber, vehicleNumber: vehicleNumber,
clearVehicle: clearVehicle,
overrideWarehouse: overrideWarehouse, overrideWarehouse: overrideWarehouse,
receivedQty: receivedQty, receivedQty: receivedQty,
}) })
@@ -1170,7 +1176,8 @@ func (s *purchaseService) ReceiveProducts(c *fiber.Ctx, id uint, req *validation
ReceivedDate: &dateCopy, ReceivedDate: &dateCopy,
TravelNumber: prep.payload.TravelNumber, TravelNumber: prep.payload.TravelNumber,
TravelDocumentPath: prep.payload.TravelDocumentPath, TravelDocumentPath: prep.payload.TravelDocumentPath,
VehicleNumber: prep.payload.VehicleNumber, VehicleNumber: prep.vehicleNumber,
ClearVehicleNumber: prep.clearVehicle,
ReceivedQty: &qtyCopy, ReceivedQty: &qtyCopy,
ProductWarehouseID: newPWID, ProductWarehouseID: newPWID,
ClearProductWarehouse: false, ClearProductWarehouse: false,