Purchase Bills (فواتير المشتريات)
Purchase Bills record supplier invoices and create accounting journal entries. They integrate with Purchase Orders for billing tracking and with Inventory for direct-mode stock receipts.
Entity Attributes
| Field | Type | Description |
|---|---|---|
id | integer | Primary key |
bill_number | string | Auto-generated (BILL-YYYY-NNNNN) |
date | date | Bill date |
due_date | date | Payment due date |
supplier_id | integer | FK to business_partners |
supplier_name | string | Denormalized supplier name |
supplier_invoice_number | string | Supplier's own invoice reference |
supplier_invoice_date | date | Date on supplier's invoice |
purchase_order_id | integer | Optional linked PO |
currency_id | integer | FK to currencies |
exchange_rate | decimal | Currency exchange rate |
cost_center_id | integer | FK to cost_centers |
status | enum | Bill lifecycle status |
payment_status | string | pending / partial / paid |
discount_type | string | Header discount: percentage or fixed |
discount_value | decimal | Discount value |
discount_amount | decimal | Calculated discount amount |
subtotal | decimal | Sum of line totals |
tax_amount | decimal | Sum of line taxes |
total | decimal | subtotal - discount + tax |
amount_paid | decimal | Total payments applied |
balance_due | decimal | total - amount_paid |
journal_entry_id | integer | FK to journal_entries (after posting) |
Bill Item Attributes
| Field | Type | Description |
|---|---|---|
product_id | integer | FK to products |
product_variant_id | integer | Optional variant |
unit_id | integer | FK to units |
warehouse_id | integer | Target warehouse (for stock) |
quantity | decimal | Quantity billed |
unit_cost | decimal | Cost per unit |
discount_type | string | Line discount: percentage or fixed |
discount_value | decimal | Discount value |
discount_amount | decimal | Calculated discount |
tax_rate_id | integer | FK to tax_rates |
tax_rate | decimal | Tax percentage |
tax_amount | decimal | Calculated tax |
line_total | decimal | (qty * unit_cost) - discount |
Status Workflow
API Endpoints
| Method | Endpoint | Permission | Description |
|---|---|---|---|
| GET | /api/purchases/bills | purchases.bills.view | List bills with filters |
| POST | /api/purchases/bills | purchases.bills.create | Create new bill |
| GET | /api/purchases/bills/{id} | purchases.bills.view | Show bill details |
| PUT | /api/purchases/bills/{id} | purchases.bills.update | Update draft bill |
| DELETE | /api/purchases/bills/{id} | purchases.bills.delete | Delete draft bill |
| POST | /api/purchases/bills/{id}/submit-approval | purchases.bills.approve | Submit for approval |
| POST | /api/purchases/bills/{id}/approve | purchases.bills.approve | Approve bill |
| POST | /api/purchases/bills/{id}/reject | purchases.bills.approve | Reject back to draft |
| POST | /api/purchases/bills/{id}/post | purchases.bills.post | Post (creates JE + stock) |
| POST | /api/purchases/bills/{id}/cancel | purchases.bills.cancel | Cancel bill |
| POST | /api/purchases/orders/{id}/create-bill | purchases.bills.create | Create bill from PO |
Query Parameters (List)
| Param | Type | Description |
|---|---|---|
status | string | Filter by status |
payment_status | string | Filter by payment status |
supplier_id | integer | Filter by supplier |
purchase_order_id | integer | Filter by linked PO |
branch_id | integer | Filter by branch |
date_from | date | Start date range |
date_to | date | End date range |
due_date_from | date | Due date range start |
due_date_to | date | Due date range end |
supplier_invoice_number | string | Search supplier reference |
search | string | Search bill_number, supplier ref, supplier name |
Journal Entry Structure
When a bill is posted, the following journal entry is created:
| Account | Debit | Credit | Condition |
|---|---|---|---|
| Inventory Account | line_total | — | Products with track_inventory = true |
| Expense Account | line_total | — | Services / non-inventory products |
| Input Tax Account | tax_amount | — | If tax > 0 |
| Purchase Discount Account | — | discount_amount | If header discount > 0 |
| Accounts Payable | — | total | Always |
GL accounts are configured in Purchases Settings:
purchases.inventory_account_idpurchases.expense_account_idpurchases.payable_account_idpurchases.tax_receivable_account_idpurchases.discount_account_id
Direct Mode Stock
When purchases.grn_mode = 'direct', posting a bill also creates inventory receipts:
- Items are grouped by
warehouse_id - One
InventoryReceiptis created per warehouse - Each receipt is auto-approved via
ApproveReceiptaction - Only products with
track_inventory = trueand awarehouse_idare included
PO Billing Integration
- Creating a bill from a PO copies items with
remainingBillQuantity() - Posting updates each PO item's
billed_quantity - PO's
bill_statusis recalculated (not_billed/partial/billed) - Cancellation reverses billed quantities
Business Rules
- Only Draft bills can be edited or deleted
- Only Approved bills can be posted
- Bills with payments (
amount_paid > 0) cannot be cancelled - Cancellation reverses: JE, stock (if direct mode), PO billed quantities
- Posting requires at least one item and configured GL accounts
payment_statusis auto-managed: pending → partial → paid