Partial Payment & Receipt System - Documentation¶
✅ YES - Partial Payments ARE Fully Supported!¶
The system already has a complete partial payment and receipt allocation system implemented for both customers and vendors.
How It Works¶
Payment Allocation Model¶
Backend: PaymentAllocation
class PaymentAllocation(models.Model):
payment = ForeignKey(Payment)
invoice = ForeignKey(Invoice)
amount = DecimalField(max_digits=20, decimal_places=2)
Key Features: - One payment can be allocated to multiple invoices - One invoice can receive multiple partial payments - Tracks exact allocation amount per invoice
User Interface¶
Payment Registration Screen¶
Location: CreatePayment.tsx
Features: 1. Partner Selection: Choose Customer/Vendor/Employee 2. Unpaid Invoice List: Shows all POSTED invoices for selected partner 3. Allocation Grid: - Invoice Date, Due Date, Reference - Total Amount - Balance Due - Allocate Amount (editable field)
- Flexible Allocation:
- Pay full invoice amount
- Pay partial amount
- Split one payment across multiple invoices
- Leave some invoices unpaid
Example Scenarios¶
Scenario 1: Partial Payment from Customer¶
Invoice: INV-001 = AED 10,000
Customer pays: AED 6,000
Action: 1. Go to Payments → Register Customer Receipt 2. Select Customer 3. Enter Amount: 6,000 4. In allocation grid, allocate 6,000 to INV-001 5. Post Payment
Result: - Payment recorded: AED 6,000 - Invoice balance: AED 4,000 (remaining) - Invoice status: PARTIALLY_PAID
Scenario 2: One Payment for Multiple Invoices¶
Invoices: - INV-001 = AED 5,000 - INV-002 = AED 3,000 - INV-003 = AED 2,000
Customer pays: AED 7,500
Action: 1. Register Receipt: AED 7,500 2. Allocate: - INV-001: AED 5,000 (full) - INV-002: AED 2,500 (partial) - INV-003: AED 0 (skip) 3. Post Payment
Result: - INV-001: PAID - INV-002: PARTIALLY_PAID (AED 500 remaining) - INV-003: NOT_PAID
Scenario 3: Multiple Payments for One Invoice¶
Invoice: BILL-001 = AED 20,000
Payments: - Payment 1: AED 8,000 - Payment 2: AED 7,000 - Payment 3: AED 5,000
Result: Invoice fully paid with 3 separate payments
Payment States¶
The system tracks invoice payment status:
| State | Description |
|---|---|
NOT_PAID |
No payments received |
PARTIALLY_PAID |
Some payments received, balance remaining |
PAID |
Fully paid |
OVERPAID |
Received more than invoice amount |
Backend Logic¶
Allocation Creation¶
File: serializers.py
When posting a payment:
for allocation in allocations_data:
PaymentAllocation.objects.create(
payment=payment,
invoice_id=allocation['invoice_id'],
amount=allocation['amount']
)
Balance Calculation¶
The system calculates:
- Total Allocated: Sum of all PaymentAllocation.amount for an invoice
- Balance Due: Invoice.amount_total - Total Allocated
Frontend Implementation¶
Allocation Input¶
Lines 317-327 in CreatePayment.tsx:
<input
type="number"
value={allocations[inv.id] || 0}
onChange={(e) => handleAllocationChange(inv.id, parseFloat(e.target.value))}
max={inv.amount_total}
step="0.01"
/>
Validation¶
- Total allocated cannot exceed payment amount
- Shows warning if over-allocated
- Displays total allocated vs payment amount
Known Limitation (Minor)¶
Issue: Aging Report shows full invoice amount instead of remaining balance
Location: utils.py:198
Impact: Low - Aging report is still accurate for unpaid invoices
Fix Needed: Calculate amount_total - sum(allocations.amount) for each invoice
How to Use¶
For Customer Receipts:¶
- Navigate to Payments → Customer Receipts
- Click Register Receipt
- Select Customer
- Enter total amount received
- Allocate to invoices (full or partial)
- Post Payment
For Vendor Payments:¶
- Navigate to Payments → Supplier Payments
- Click Register Payment
- Select Vendor
- Enter total amount to pay
- Allocate to bills (full or partial)
- Post Payment
Direct from Invoice:¶
- Open any invoice
- Click Register Payment button
- Amount pre-filled with invoice total
- Adjust allocation as needed
- Post Payment
Conclusion¶
✅ Partial payments are fully supported
✅ Works for Customers, Vendors, and Employees
✅ Flexible allocation across multiple invoices
✅ Tracks payment history per invoice
✅ Production-ready
The only minor enhancement needed is updating the Aging Report to show remaining balances instead of total amounts.