mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
feat[BE]: Enhance payment allocation logic to support FIFO consumption for sales transactions
This commit is contained in:
@@ -464,9 +464,13 @@ func (s *repportService) GetCustomerPayment(ctx *fiber.Ctx, params *validation.C
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
result = append(result, item)
|
||||
|
||||
if len(item.Rows) > 0 {
|
||||
result = append(result, item)
|
||||
}
|
||||
}
|
||||
|
||||
totalCustomers = int64(len(result))
|
||||
return result, totalCustomers, nil
|
||||
}
|
||||
|
||||
@@ -503,14 +507,8 @@ func (s *repportService) processCustomerPayment(ctx context.Context, customerID
|
||||
row.Status = status
|
||||
|
||||
if status == "LUNAS" {
|
||||
if previousBalance >= tx.TotalPrice {
|
||||
days := 0
|
||||
row.AgingDay = &days
|
||||
} else if paymentDate != nil {
|
||||
if paymentDate != nil {
|
||||
days := int(paymentDate.Sub(tx.TransDate).Hours() / 24)
|
||||
if days < 0 {
|
||||
days = 0
|
||||
}
|
||||
row.AgingDay = &days
|
||||
} else {
|
||||
days := 0
|
||||
@@ -518,9 +516,6 @@ func (s *repportService) processCustomerPayment(ctx context.Context, customerID
|
||||
}
|
||||
} else {
|
||||
days := int(time.Since(tx.TransDate).Hours() / 24)
|
||||
if days < 0 {
|
||||
days = 0
|
||||
}
|
||||
row.AgingDay = &days
|
||||
}
|
||||
} else if tx.TransactionType == "PAYMENT" {
|
||||
@@ -586,6 +581,67 @@ func (s *repportService) determineSalesStatusAndPaymentDate(transactions []reppo
|
||||
// 4. BELUM LUNAS: no payment at all
|
||||
|
||||
if previousBalance >= currentSales.TotalPrice {
|
||||
// Cari payment yang digunakan untuk melunasi sales ini dengan FIFO
|
||||
// Track payment allocations that are consumed by previous sales
|
||||
type paymentAllocation struct {
|
||||
date time.Time
|
||||
amount float64
|
||||
consumed float64
|
||||
}
|
||||
allocations := []paymentAllocation{}
|
||||
runningBalance := 0.0
|
||||
|
||||
// Process all transactions before current sales to build allocation map
|
||||
for i := 0; i < currentIndex; i++ {
|
||||
if transactions[i].TransactionType == "PAYMENT" {
|
||||
allocations = append(allocations, paymentAllocation{
|
||||
date: transactions[i].TransDate,
|
||||
amount: transactions[i].PaymentAmount,
|
||||
consumed: 0,
|
||||
})
|
||||
runningBalance += transactions[i].PaymentAmount
|
||||
} else if transactions[i].TransactionType == "SALES" {
|
||||
salesAmount := transactions[i].TotalPrice
|
||||
remainingToConsume := salesAmount
|
||||
|
||||
// Consume from oldest allocations first (FIFO)
|
||||
for j := range allocations {
|
||||
if remainingToConsume <= 0 {
|
||||
break
|
||||
}
|
||||
available := allocations[j].amount - allocations[j].consumed
|
||||
if available > 0 {
|
||||
consume := available
|
||||
if consume > remainingToConsume {
|
||||
consume = remainingToConsume
|
||||
}
|
||||
allocations[j].consumed += consume
|
||||
remainingToConsume -= consume
|
||||
}
|
||||
}
|
||||
runningBalance -= salesAmount
|
||||
}
|
||||
}
|
||||
|
||||
// Now find which allocation covers the current sales
|
||||
amountNeeded := currentSales.TotalPrice
|
||||
for _, alloc := range allocations {
|
||||
available := alloc.amount - alloc.consumed
|
||||
if available > 0 {
|
||||
if amountNeeded <= available {
|
||||
// This allocation fully covers the sales
|
||||
return "LUNAS", &alloc.date
|
||||
} else {
|
||||
// This allocation partially covers, continue to next
|
||||
amountNeeded -= available
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we get here, use the oldest allocation
|
||||
if len(allocations) > 0 {
|
||||
return "LUNAS", &allocations[0].date
|
||||
}
|
||||
return "LUNAS", nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user