# PostAccountPayableDocument

## Permission Scope

accountPayableDocument

## Overview

postAccountPayableDocument posts a REGISTERED AP document. The command requires the document currency to equal the company's base currency, resolves the accounting period for the document posting date, creates a balanced JournalEntry from the AP distributions and payable control account, posts that journal entry directly in financial-accounting, and moves the AP document to POSTED in the same transaction. Posting refuses to post while any active hold remains.

For purchase-order sourced lines that carry a price variance — non-correction lines whose unit price differs from the matched purchase order unit price, PRICE correction lines, and QUANTITY correction lines — posting also calls inventory's `postAcquisitionCostAdjustment` once in the same transaction with variance kind INVOICE_PRICE, passing the document and one line per such document line — each with the generic source reference to the AP document line, the purchase order line (`purchaseOrderId`/`purchaseOrderLineId`), and the signed variance amount — so invoice-driven receipt cost corrections land atomically with the AP posting. AP owns the variance declaration: the amount is the change the line causes in the order line's total invoice price variance, measured against the line's `matchedPurchaseOrderUnitPrice` — line quantity times the price difference (times the correction unit price for PRICE corrections), negated on CREDIT_MEMO documents. Inventory owns the state and the distribution: it registers every declared amount and redistributes the cumulative variance over the order line's receipt layers, so AP does no clamping and tracks no billed quantities. Lines whose amount is zero are skipped, and a document with no non-zero variance lines triggers no call.

## Business Rules

- Only REGISTERED AP documents can be posted
- The AP document currency must equal the company's base currency because financial-accounting journal lines are base-currency amounts
- Posting fails when the AP document has any active (unreleased) payment hold
- Posting uses the payable control account stored on the AP document header
- AP distribution accounts and the stored payable control account must exist and be ACTIVE
- Distribution total must match the document total
- INVOICE debits AP distribution accounts and credits the payable control account; a negative derived amount (an invoice price variance row billed below the order price) flips to the opposite side at its absolute value
- CREDIT_MEMO debits the payable control account and credits AP distribution accounts, flipping every line uniformly
- The journal entry uses source document type ACCOUNT_PAYABLE_DOCUMENT and source document id equal to the AP document id
- The journal entry date is the AP document posting date and its period is resolved for the AP document company
- Journal entry creation and posting failures are returned as AP posting failures
- After the AP journal posts, all purchase-order sourced lines with a non-zero price variance are sent in one inventory `postAcquisitionCostAdjustment` call in the same transaction with variance kind INVOICE_PRICE, one line per document line with its signed variance amount
- Non-correction lines and QUANTITY correction lines declare their quantity times the difference between the line unit price and the line's `matchedPurchaseOrderUnitPrice`, negated when the document is a CREDIT_MEMO; a purchase-order sourced non-PRICE line without that snapshot fails the posting
- PRICE correction lines reprice already-billed units without changing the billed quantity; they declare their quantity times the correction unit price, negated when the document is a CREDIT_MEMO
- AMOUNT corrections and amount-only lines trigger no adjustment; lines whose amount is zero are skipped
- Acquisition cost adjustment failures fail the AP posting and abort the transaction
- Successful posting sets postedAt on the AP document

## Process Flow

```mermaid
flowchart TD
    A[Receive post AP document request] --> B{Document exists?}
    B -->|No| C[Return error: AP document not found]
    B -->|Yes| D{Status is REGISTERED?}
    D -->|No| E[Return error: invalid AP document status]
    D -->|Yes| Q{Any active hold?}
    Q -->|Yes| R[Return error: AP document has active hold]
    Q -->|No| F{Distributions valid?}
    F -->|No| G[Return validation error]
    F -->|Yes| J{Accounts valid?}
    J -->|No| K[Return account error]
    J -->|Yes| L[Resolve accounting period]
    L --> M[Create balanced journal entry]
    M --> N{Journal entry posting succeeds?}
    N -->|No| S[Return AP journal posting failure]
    N -->|Yes| T[Call inventory postAcquisitionCostAdjustment once with a line per PO-sourced line carrying a non-zero signed variance amount]
    T -->|Failure| U[Return AP acquisition cost adjustment failure]
    T -->|Success| O[Set AP document POSTED]
    O --> P[Return posted AP document]
```

## External Dependencies

- [coa-management::ListAccounts](../../../coa-management/docs/query/ListAccounts.md) - Validates payable control and distribution GL accounts exist and are ACTIVE
- [financial-accounting::GetPeriodByDate](../../../financial-accounting/docs/query/GetPeriodByDate.md) - Resolves the accounting period for the posting date
- [financial-accounting::CreateJournalEntry](../../../financial-accounting/docs/command/CreateJournalEntry.md) - Creates the source-referenced AP journal entry
- [financial-accounting::PostJournalEntry](../../../financial-accounting/docs/command/PostJournalEntry.md) - Posts the journal entry into the general ledger
- [inventory::PostAcquisitionCostAdjustment](../../../inventory/docs/command/PostAcquisitionCostAdjustment.md) - Posts invoice-driven receipt cost corrections for purchase-order sourced lines in the same transaction

## Error Scenarios

- **AP_DOCUMENT_NOT_FOUND**: Referenced AP document does not exist
- **AP_INVALID_DOCUMENT_STATUS**: AP document status does not allow this operation
- **COMPANY_NOT_FOUND**: Referenced company does not exist
- **AP_POSTING_CURRENCY_MISMATCH**: AP document currency does not match the company base currency
- **AP_DOCUMENT_HAS_ACTIVE_HOLD**: AP document cannot be posted while it has an active payment hold
- **AP_MINIMUM_LINES_NOT_MET**: AP document must have at least one line and one distribution
- **AP_LINE_TOTAL_MISMATCH**: AP line gross total or distribution total does not match the document total
- **ACCOUNT_NOT_FOUND**: Referenced GL account does not exist
- **ACCOUNT_INACTIVE**: Referenced GL account is not ACTIVE
- **AP_ACCOUNTING_PERIOD_NOT_FOUND**: No accounting period covers the AP document posting date
- **AP_JOURNAL_ENTRY_CREATE_FAILED**: Journal entry creation failed for the AP document
- **AP_JOURNAL_ENTRY_POST_FAILED**: Journal entry posting failed for the AP document
- **AP_ACQUISITION_COST_ADJUSTMENT_FAILED**: Inventory acquisition cost adjustment failed for a purchase-order sourced line

## Test Cases

- posts REGISTERED invoice AP document and posts a balanced journal entry
- posts REGISTERED credit memo AP document and posts a reversed balanced journal entry
- returns error when AP document does not exist
- returns error when AP document is not REGISTERED
- returns error when company does not exist
- returns error when AP document currency differs from company base currency
- returns error when AP document has an active payment hold
- returns error when distribution total does not match document total
- returns error when line gross total does not match document total
- returns error when a line distribution total does not match line gross amount
- returns error when payable control account does not exist
- returns error when payable control account is inactive
- returns error when distribution account is inactive
- returns error when no accounting period covers the posting date
- returns error when journal entry creation fails
- returns error when journal entry posting fails
- calls inventory acquisition cost adjustment once with a line per purchase-order sourced variance
- skips the acquisition cost adjustment when the invoiced unit price equals the purchase order unit price
- declares no variance when the order was repriced after the line was matched
- passes the full variance amount for an invoice billed beyond receipts
- passes a negative variance amount for a non-correction credit memo purchase line
- passes a signed per-unit delta for PRICE correction lines and skips AMOUNT corrections
- declares the variance of a QUANTITY correction against the order unit price
- does not call inventory acquisition cost adjustment for amount-only lines
- returns error and aborts the transaction when the acquisition cost adjustment fails
