# ReverseOutgoingPayment

## Permission Scope

outgoingPayment

## Overview

reverseOutgoingPayment reverses a POSTED outgoing payment by changing the same payment header to REVERSED, adding corresponding reversing settlement rows, and posting an opposite journal entry directly in financial-accounting. The original posting facts remain preserved on the payment and the reversal is atomic.

## Business Rules

- Input includes only the original payment `id` and `reversalDate`
- The payment must be POSTED and not already REVERSED
- The same payment header transitions to REVERSED and retains its original ID, payment date, amount, posting timestamp, and custom fields
- The supplied `reversalDate` is stored separately from the original `paymentDate`, and `reversedAt` records when the command completed
- Each reversing settlement copies the original due schedule and amount and links through `reversalOfSettlementId`
- Reversal decreases effective settled amounts but cannot make a due schedule's effective settled amount negative
- Reversal locks affected due schedules in deterministic ID order before reading effective settlements
- Reversal accounting debits the original payment account, credits payable control accounts for reversed invoice settlements, and debits payable control accounts for reversed credit memo settlements
- Journal creation and posting, payment status update, and reversing settlement creation succeed or fail as one operation
- Original settlement rows remain unchanged

## Process Flow

```mermaid
flowchart TD
    A[Receive reversal request] --> B{Original exists and is POSTED?}
    B -->|No| X[Return payment error]
    B -->|Yes| C{Payment is not already REVERSED?}
    C -->|No| Y[Return reversal error]
    C -->|Yes| D{Effective settlements remain non-negative?}
    D -->|No| Z[Return reversal error]
    D -->|Yes| E[Create linked reversing settlements under the same payment]
    E --> F[Build opposite journal entry]
    F --> H{Create and post journal succeeds?}
    H -->|No| I[Roll back and return journal failure]
    H -->|Yes| J[Set original payment to REVERSED and return it]
```

## External Dependencies

- [financial-accounting::GetPeriodByDate](../../../financial-accounting/docs/query/GetPeriodByDate.md) - Resolves the reversal accounting period
- [financial-accounting::CreateJournalEntry](../../../financial-accounting/docs/command/CreateJournalEntry.md) - Creates the reversal journal
- [financial-accounting::PostJournalEntry](../../../financial-accounting/docs/command/PostJournalEntry.md) - Posts the reversal journal

## Error Scenarios

- **OUTGOING_PAYMENT_NOT_FOUND**: Payment does not exist
- **OUTGOING_PAYMENT_INVALID_STATUS**: Payment status does not allow this operation
- **OUTGOING_PAYMENT_ALREADY_REVERSED**: A reversal already exists for the original payment
- **OUTGOING_PAYMENT_REVERSAL_NOT_ALLOWED**: Reversal would make effective settlement negative
- **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

- marks the original payment REVERSED and adds reversing settlements under the same header
- updates only reversal metadata and does not copy settlement custom fields
- serializes settlement changes through deterministically ordered due-schedule locks
- posts journal lines exactly opposite to the original payment using the original payment ID
- reverses the net journal for invoice and credit memo settlements
- returns errors for missing, non-POSTED, already reversed, or ineffective payments
- returns error when the reversal date has no accounting period
- rolls back when journal entry creation or posting fails
