# CreatePartnerBankAccount

## Permission Scope

partnerDetail

## Overview

createPartnerBankAccount adds reusable bank details through the owning BusinessPartner aggregate. A non-empty accountNumber is required. Account-specific purposes and default selection are modeled in CustomerBankAccountUsage and SupplierBankAccountUsage. New bank details may be added only while the partner is active; existing details remain available for correction while inactive.

## Business Rules

- Partner must exist in the system
- The owning BusinessPartner aggregate is loaded with a row lock before bank details are added
- Partner must be active to receive new bank details
- Bank name is required and must be non-empty
- Account holder name is required and must be non-empty
- Account number must be provided and must be non-empty
- `routingNumber` is optional — used for domestic routing conventions (e.g., ACH/wire)
- Currency must reference an existing Currency in the primitives module
- Purpose and default selection are not stored on PartnerBankAccount

## Process Flow

```mermaid
flowchart TD
    A[Receive create request] --> B[Lock and load BusinessPartner aggregate]
    B --> C{Partner exists?}
    C -->|No| D[Return error: partner not found]
    C -->|Yes| E{Currency exists?}
    E -->|No| F[Return error: currency not found]
    E -->|Yes| G{Partner status is ACTIVE?}
    G -->|No| H[Return error: partner inactive]
    G -->|Yes| I{Bank name, holder and account number non-empty?}
    I -->|No| J[Return validation error]
    I -->|Yes| K[Add bank details to aggregate]
    K --> L[Save aggregate and return bank account ID]
```

## External Dependencies

- [primitives::Currency](../../../primitives/docs/model/Currency.md) - Validates that the referenced currency exists

## Error Scenarios

- **PARTNER_NOT_FOUND**: Specified partner ID does not exist
- **PARTNER_INACTIVE**: Partner status is `INACTIVE`
- **CURRENCY_NOT_FOUND**: Referenced currency does not exist
- **MISSING_ACCOUNT_IDENTIFIER**: Account number is empty or not provided
- **INVALID_BANK_NAME**: Bank name is empty, whitespace-only, or not provided
- **INVALID_ACCOUNT_HOLDER_NAME**: Account holder name is empty, whitespace-only, or not provided

## Test Cases

- adds bank details through the BusinessPartner aggregate
- rejects adding bank details to an inactive partner
- returns error when the partner does not exist
- returns error when the currency does not exist

The parameterized `rejects invalid bank details %#` test covers empty bank names, empty account holder names, and empty or whitespace-only account numbers.
