# Purchase Module

Implemented:

- Supplier master data: see `docs/customer-supplier-module.md`.
- Purchase orders at `/purchase-orders`.
- Goods receipts at `/goods-receipts`.
- Purchase invoices at `/purchase-invoices`.
- Purchase returns at `/purchase-returns`.
- Supplier payments at `/supplier-payments`.

## Purchase Order Rules

- Purchase orders are draft documents with no stock or accounting impact.
- Document numbers use branch, company, and fiscal-year scoped `PO-000001` sequences.
- Lines require active items and warehouses belonging to the selected company and branch.
- PO statuses: draft, confirmed, partially_received, received, cancelled.

## Goods Receipt Rules

- Goods receipts are posted documents that receive inventory at purchase cost.
- Posting runs inside `GoodsReceiptService::createAndPost()` as one transaction.
- Document numbers use branch, company, and fiscal-year scoped `GRN-000001` sequences.
- Posting creates an inbound `receipt` stock movement. No journal entry is created at this stage.
- Stock cost is captured and stored on the receipt lines for later use by purchase invoice.
- Every posted receipt records an audit log event `GoodsReceipt.posted`.

## Purchase Invoice Rules

- Purchase invoices are posted documents only; posted invoices are immutable.
- Posting runs inside `PurchaseInvoiceService::createAndPost()` as one transaction.
- Document numbers use branch, company, and fiscal-year scoped `PI-000001` sequences.
- Purchase type is either `credit` or `cash`.
- Credit purchase invoices require an active branch-scoped supplier and credit the supplier payable account.
- Cash purchase invoices require a cash party name, store no supplier, and credit the seeded Cash in Hand account.
- The fiscal period is resolved automatically from the invoice date and selected open fiscal year.
- Current invoice lines support active inventory-tracked items only.
- Line warehouse, batch, expiry, serial, and stock availability are validated by the stock movement engine.
- Posting creates a stock receipt through `StockMovementService` at **net cost** (after line discount).
- Posting creates a balanced journal entry: Dr Inventory (net cost), Dr Input Tax (if present), Cr Supplier Payable or Cash/Bank (grand total).
- Required seeded posting accounts are Merchandise Inventory, Input Tax Payable, Cash in Hand for cash purchases, and the supplier's payable account for credit purchases.
- Every posted invoice records an audit log event `PurchaseInvoice.posted`.

## Purchase Return Rules

- Purchase returns are posted documents only and must reference a posted purchase invoice.
- The current supplier return workflow accepts credit purchase invoices only.
- Posting runs inside `PurchaseReturnService::createAndPost()` as one transaction.
- Return document numbers use branch, company, and fiscal-year scoped `PR-000001` sequences.
- Return date must be inside the selected open fiscal period and cannot be before the original invoice date.
- Return lines must reference original purchase invoice lines; price, discount, tax, and cost are derived from the original invoice line.
- Return quantity cannot exceed the invoice line quantity remaining after previous posted returns.
- Posting creates an outbound `purchase_return` stock movement using the original invoice net unit cost.
- Posting creates a balanced journal entry that debits supplier payable, credits inventory, and credits input tax when present.
- Every posted return records an audit log event `PurchaseReturn.posted`.
- The returns listing shows the invoice's purchase type and the ref purchase invoice number, matching the purchase invoice listing columns.
- Listing filters: branch and purchase type; search spans return number, ref purchase invoice number, supplier name/code, and cash party name.

## Supplier Payment Rules

- Supplier payments are posted documents only.
- Posting runs inside `SupplierPaymentService::createAndPost()` as one transaction.
- Document numbers use branch, company, and fiscal-year scoped `SPP-000001` sequences.
- Payment methods: cash, bank, card, wallet. Non-cash methods require a bank account.
- Posting creates a balanced journal entry: Dr Supplier Payable, Cr Bank/Cash account.
- Every posted payment records an audit log event `SupplierPayment.posted`.

## Accounting Entries

### Purchase Invoice
| Account | Debit | Credit |
|---------|-------|--------|
| Merchandise Inventory | Net cost | |
| Input Tax Payable | Tax amount (if present) | |
| Supplier Payable or Cash/Bank | | Grand total |

### Purchase Return
| Account | Debit | Credit |
|---------|-------|--------|
| Supplier Payable | Grand total | |
| Merchandise Inventory | | Return cost |
| Input Tax Payable | | Tax amount (if present) |

### Supplier Payment
| Account | Debit | Credit |
|---------|-------|--------|
| Supplier Payable | Payment amount | |
| Bank/Cash | | Payment amount |

## Deferred Work

- Purchase order approvals and workflows.
- Goods receipt link to purchase order for partial receiving.
- Landed cost allocation.
- Three-way matching (PO → GRN → PI).
