# PostOutgoingPayment

## Permission Scope

outgoingPayment

## Overview

postOutgoingPayment validates a complete DRAFT payment, makes its settlement allocations effective, creates and posts a balanced journal entry directly in financial-accounting, and moves the payment to POSTED atomically.

## Business Rules

- Input includes payment `id`
- The payment must be DRAFT and have at least one settlement
- Company, supplier, currency, and payment account eligibility are revalidated at posting
- Settlement amounts must be positive; their signed total, using each target document's `documentType`, must equal the payment total
- Every target due schedule line must belong to a POSTED INVOICE or CREDIT_MEMO with the same company, supplier, and currency as the payment
- Target AP document rows are locked while settlement eligibility is validated
- The cumulative effective POSTED settlement amount for each due schedule line, including this payment and net of reversals, cannot exceed its due schedule amount
- Over-settlement validation and the POSTED transition must be protected against concurrent posting
- The journal source type is OUTGOING_PAYMENT and source id is the payment id
- The journal date is the payment date and its accounting period is resolved from that date
- Normal payment accounting debits payable control accounts for invoice settlements, credits payable control accounts for credit memo settlements, and credits the payment account by the net payment total
- Journal creation, journal posting, and the payment status transition succeed or fail as one operation
- A successful post records `postedAt`; the payment and settlements are thereafter immutable
- Repeating a post for an already POSTED payment is rejected

## Process Flow

```mermaid
flowchart TD
    A[Receive post request] --> B{Payment exists and is DRAFT?}
    B -->|No| X[Return payment error]
    B -->|Yes| C{Master data remains eligible?}
    C -->|No| Y[Return master-data error]
    C -->|Yes| D{Settlements exist and signed net equals total?}
    D -->|No| Z[Return total or settlement error]
    D -->|Yes| E{Targets are eligible POSTED AP documents?}
    E -->|No| T[Return target error]
    E -->|Yes| F{Atomic cumulative balance check passes?}
    F -->|No| O[Return over-settlement]
    F -->|Yes| G[Build balanced journal entry]
    G --> H{Create and post journal succeeds?}
    H -->|No| I[Return journal failure]
    H -->|Yes| J[Set payment POSTED and postedAt]
    J --> K[Return posted payment]
```

## External Dependencies

- [organization::GetCompany](../../../organization/docs/query/GetCompany.md) - Revalidates company status
- [business-partner::GetSupplierAccount](../../../business-partner/docs/query/GetSupplierAccount.md) - Revalidates supplier account company and transaction availability
- [primitives::GetCurrency](../../../primitives/docs/query/GetCurrency.md) - Revalidates currency existence
- [coa-management::GetAccount](../../../coa-management/docs/query/GetAccount.md) - Revalidates the payment account
- [financial-accounting::CreateJournalEntry](../../../financial-accounting/docs/command/CreateJournalEntry.md) - Creates the outgoing payment journal
- [financial-accounting::PostJournalEntry](../../../financial-accounting/docs/command/PostJournalEntry.md) - Posts the outgoing payment journal

## Error Scenarios

- **OUTGOING_PAYMENT_NOT_FOUND**: Payment does not exist
- **OUTGOING_PAYMENT_INVALID_STATUS**: Payment status does not allow this operation
- **OUTGOING_PAYMENT_INVALID_AMOUNT**: Payment total or settlement amount is not positive
- **OUTGOING_PAYMENT_SETTLEMENT_INVALID**: Settlement set is empty where required, duplicated, or internally inconsistent
- **OUTGOING_PAYMENT_TOTAL_MISMATCH**: Signed settlement amount total differs from payment total
- **OUTGOING_PAYMENT_TARGET_INELIGIBLE**: Settlement target is not an eligible AP due schedule
- **OUTGOING_PAYMENT_OVER_SETTLEMENT**: Posting would make a due schedule's effective settled amount exceed its amount
- **COMPANY_NOT_FOUND**: Referenced company does not exist
- **COMPANY_INACTIVE**: Referenced company is not ACTIVE
- **AP_SUPPLIER_ACCOUNT_NOT_FOUND**: Referenced supplier account does not exist
- **AP_INVALID_SUPPLIER_ACCOUNT**: Business partner is unavailable for transactions or belongs to another company
- **AP_CURRENCY_NOT_FOUND**: Referenced currency does not exist
- **ACCOUNT_NOT_FOUND**: Referenced GL account does not exist
- **ACCOUNT_INACTIVE**: Referenced GL account is not ACTIVE
- **ACCOUNT_COMPANY_MISMATCH**: Referenced account belongs to a different company
- **OUTGOING_PAYMENT_ACCOUNTING_PERIOD_NOT_FOUND**: No accounting period covers the posting date
- **OUTGOING_PAYMENT_JOURNAL_ENTRY_CREATE_FAILED**: Journal entry creation failed
- **OUTGOING_PAYMENT_JOURNAL_ENTRY_POST_FAILED**: Journal entry posting failed

## Test Cases

- allows an active account when the partner is inactive

- posts a complete DRAFT payment and posts the expected journal entry
- supports partial settlement and settlement of multiple due schedule lines
- supports a later payment against a partially settled due schedule
- rejects a missing, POSTED, or CANCELLED payment
- rejects a payment without settlements or whose signed settlement total differs from total
- rejects a non-positive settlement amount
- rejects a due schedule whose parent is not a supported POSTED AP document
- rejects a target with different company, supplier, or currency
- nets a posted invoice and CREDIT_MEMO correction into one outgoing payment
- allows an AP-increasing INVOICE correction document as a settlement target
- locks target invoices while validating settlement eligibility
- rejects cumulative over-settlement including concurrent attempts
- nets posted reversal settlements when calculating effective settled amount
- rejects posting when company, supplier, currency, or payment account is no longer eligible
- leaves the payment DRAFT when journal entry creation fails
- leaves the payment DRAFT when journal entry posting fails
