Purchase Payments (مدفوعات المشتريات)
Purchase payments record supplier payments against posted purchase bills. Payments track the paying GL account and support partial payments, check details, and payment schedules.
Entity Attributes
PurchasePayment
| Field | Type | Required | Description |
|---|---|---|---|
id | integer | auto | Primary key |
company_id | FK | auto | Company |
branch_id | FK | auto | Inherited from bill |
payment_number | string | auto | Auto-generated PPAY-YYYY-NNNNN |
date | date | yes | Payment date |
bill_id | FK | yes | Source purchase bill (must be posted) |
supplier_id | FK | auto | Inherited from bill |
amount | decimal(15,3) | yes | Payment amount |
currency_id | FK | no | Optional foreign currency |
exchange_rate | decimal(15,6) | auto | Default 1.000000 |
payment_method | enum | yes | cash, bank_transfer, check, credit_card |
bank_account_id | FK | no | Bank account for bank/check payments |
check_number | string(50) | no | Check reference number |
check_date | date | no | Check clearing date |
check_bank | string | no | Issuing bank name |
reference | string | no | External reference |
notes | text | no | Notes (EN) |
notes_ar | text | no | Notes (AR) |
paying_account_id | FK | yes | GL account paying from (Cash/Bank) |
journal_entry_id | FK | auto | Linked JE (after posting) |
status | enum | auto | Current workflow status |
PurchasePaymentSchedule
| Field | Type | Required | Description |
|---|---|---|---|
id | integer | auto | Primary key |
bill_id | FK | auto | Parent bill |
installment_number | integer | yes | Sequential position |
due_date | date | yes | Installment due date |
amount | decimal(15,3) | yes | Installment amount |
amount_paid | decimal(15,3) | auto | Paid to date |
status | enum | auto | pending, partially_paid, paid, overdue |
ER Diagram
Workflow / Status Diagram
API Endpoints
| Method | Endpoint | Permission | Description |
|---|---|---|---|
| GET | /api/purchases/payments | purchases.payments.view | List payments |
| POST | /api/purchases/payments | purchases.payments.create | Create payment |
| GET | /api/purchases/payments/{id} | purchases.payments.view | Show payment |
| PUT | /api/purchases/payments/{id} | purchases.payments.update | Update draft |
| DELETE | /api/purchases/payments/{id} | purchases.payments.delete | Delete draft |
| POST | /api/purchases/payments/{id}/post | purchases.payments.post | Post payment |
| POST | /api/purchases/payments/{id}/cancel | purchases.payments.cancel | Cancel payment |
| GET | /api/purchases/bills/{id}/payments | purchases.payments.view | List bill payments |
| GET | /api/purchases/bills/{id}/payment-schedule | purchases.payments.view | Bill schedule |
Query Parameters (Index)
| Parameter | Type | Description |
|---|---|---|
status | string | Filter by status: draft, posted, cancelled |
supplier_id | integer | Filter by supplier |
bill_id | integer | Filter by source bill |
payment_method | string | Filter by method: cash, bank_transfer, check, credit_card |
branch_id | integer | Filter by branch |
date_from | date | Start date filter |
date_to | date | End date filter |
search | string | Search payment_number, reference, check_number |
Create Request
bash
curl -X POST /api/purchases/payments \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"bill_id": 1,
"date": "2026-02-25",
"amount": 500.000,
"payment_method": "bank_transfer",
"paying_account_id": 5,
"bank_account_id": 2,
"reference": "TRF-2026-001"
}'dart
final response = await dio.post(
'/api/purchases/payments',
data: {
'bill_id': 1,
'date': '2026-02-25',
'amount': 500.000,
'payment_method': 'bank_transfer',
'paying_account_id': 5,
'bank_account_id': 2,
'reference': 'TRF-2026-001',
},
);Business Rules
- Source Bill: Payments can only be created against posted bills (
status = postedor later) - Amount Validation: Payment amount must not exceed the bill's
balance_due - Posting creates AP JE:
- DR: Accounts Payable (reduces AP balance, with partner_id)
- CR: Paying Account (Cash/Bank — the account paying from)
- Bill Update on Post: Increments
amount_paid, recalculatesbalance_due, updatespayment_status(pending → partial → paid) and billstatus(Posted → PartiallyPaid → Paid) - Schedule Allocation: On posting, allocates payment to oldest unpaid installments first; updates each schedule's
amount_paidandstatus - Cancellation: Reverses the JE, decrements bill
amount_paid, recalculates payment status, and deallocates from schedules (newest paid first)
Sequence
Payments use auto-generated numbers with prefix PPAY (Purchase Payment):
- Format:
PPAY-{YYYY}-{NNNNN}(e.g.,PPAY-2026-00001) - Reset frequency: Yearly