> For the complete documentation index, see [llms.txt](https://host2host.onibonje.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://host2host.onibonje.com/docs/29-canonical-data-model.md).

# Canonical Data Model

## 1. Overview

The **canonical data model** is the internal standard format between transformation, validation, Finacle posting, ACK generation, audit, and events. All inbound formats (CSV, ISO 20022, XML, JSON) map **to** canonical; all outbound formats map **from** canonical.

**Module:** `h2h-common` (`com.heirs.h2h.common.model`)

***

## 2. Design Principles

| Principle           | Rule                                                              |
| ------------------- | ----------------------------------------------------------------- |
| Finacle-agnostic    | No Finacle field names in canonical types                         |
| Immutable records   | Java records for thread safety                                    |
| Extensible metadata | `Map<String, String> extensions` + custom attributes from context |
| Versioned           | `modelVersion` field for schema evolution                         |
| Audit-friendly      | All types implement `Auditable` with correlationId                |

***

## 3. Entity Relationship

```mermaid
erDiagram
  PaymentBatch ||--o{ PaymentInstruction : contains
  PaymentBatch ||--o| FileMetadata : sourced_from
  PaymentInstruction ||--o| PaymentResult : produces
  PaymentBatch ||--o| AcknowledgementFile : generates
  CollectionBatch ||--o{ CollectionInstruction : contains
  StatementRequest ||--|| StatementDelivery : produces

  PaymentBatch {
    string batchId
    string partnerId
    string correlationId
    string messageType
    int totalCount
    decimal totalAmount
    string currency
  }

  PaymentInstruction {
    string instructionId
    string debitAccount
    string creditAccount
    decimal amount
    string currency
    string narrative
    string customerReference
  }

  PaymentResult {
    string bankReference
    string status
    string errorCode
  }
```

***

## 4. Core Types

### 4.1 PaymentBatch

| Field           | Type                      | Required | Description                 |
| --------------- | ------------------------- | -------- | --------------------------- |
| `batchId`       | String                    | Yes      | Platform-generated          |
| `correlationId` | String                    | Yes      | End-to-end trace            |
| `partnerId`     | String                    | Yes      | Partner code                |
| `countryCode`   | String                    | Yes      | ISO 3166-1 alpha-2          |
| `messageType`   | String                    | Yes      | BULK\_PAYMENT, SALARY, etc. |
| `currency`      | String                    | Yes      | ISO 4217                    |
| `totalCount`    | int                       | Yes      | Line count                  |
| `totalAmount`   | BigDecimal                | Yes      | Sum of lines                |
| `valueDate`     | LocalDate                 | Yes      | Payment date                |
| `instructions`  | List\<PaymentInstruction> | Yes      | Payment lines               |
| `extensions`    | Map                       | No       | Custom attributes           |
| `modelVersion`  | String                    | Yes      | e.g. `1.0`                  |

### 4.2 PaymentInstruction

| Field               | Type       | Required    | Description         |
| ------------------- | ---------- | ----------- | ------------------- |
| `instructionId`     | String     | Yes         | Unique within batch |
| `debitAccount`      | String     | Yes         | Originator account  |
| `creditAccount`     | String     | Yes         | Beneficiary account |
| `creditBankCode`    | String     | Conditional | For inter-bank      |
| `beneficiaryName`   | String     | Yes         |                     |
| `amount`            | BigDecimal | Yes         | Must be > 0         |
| `currency`          | String     | Yes         |                     |
| `narrative`         | String     | No          | Max 140 chars       |
| `customerReference` | String     | No          | Partner reference   |
| `paymentType`       | String     | No          | SALARY, VENDOR, TAX |
| `extensions`        | Map        | No          | e.g. `NG_CBN_REF`   |

### 4.3 PaymentResult

| Field           | Type    | Description                                          |
| --------------- | ------- | ---------------------------------------------------- |
| `instructionId` | String  | FK to instruction                                    |
| `bankReference` | String  | Finacle reference                                    |
| `status`        | Enum    | SUCCESS, FAILED, PENDING                             |
| `errorCode`     | String  | From [error catalog](/docs/31-error-code-catalog.md) |
| `errorMessage`  | String  | Human-readable                                       |
| `postedAt`      | Instant | Finacle post time                                    |

### 4.4 CollectionBatch / CollectionInstruction

Mirror payment structure with `mandateReference`, `payerAccount`, `collectionType` (BILL, TAX, UTILITY).

### 4.5 AcknowledgementFile

| Field         | Type                 | Description                      |
| ------------- | -------------------- | -------------------------------- |
| `batchId`     | String               | Source batch                     |
| `format`      | String               | CSV, XML, JSON                   |
| `status`      | Enum                 | FULL\_SUCCESS, PARTIAL, REJECTED |
| `lineResults` | List\<PaymentResult> | Per-line outcomes                |
| `generatedAt` | Instant              |                                  |

### 4.6 StatementRequest / StatementDelivery

For MT940/camt — see [Transformation and Messaging](/docs/24-transformation-and-messaging.md).

***

## 5. Lifecycle States

```mermaid
stateDiagram-v2
  [*] --> RECEIVED
  RECEIVED --> VALIDATED
  VALIDATED --> TRANSFORMED
  TRANSFORMED --> POSTING
  POSTING --> POSTED
  POSTING --> PARTIAL
  POSTING --> REJECTED
  POSTED --> ACK_GENERATED
  PARTIAL --> ACK_GENERATED
  REJECTED --> NACK_GENERATED
  ACK_GENERATED --> DELIVERED
  NACK_GENERATED --> DELIVERED
  DELIVERED --> [*]
```

Stored in `payment_batch.status` and propagated via `H2hContext.status`.

***

## 6. Mapping Boundaries

| Direction                    | Responsibility                                                     |
| ---------------------------- | ------------------------------------------------------------------ |
| Inbound file/API → Canonical | `h2h-transform-*` via `transform_spec`                             |
| Canonical → CBS request      | `CoreBankingIntegration` via `h2h-finacle-wrapper` OperationMapper |
| Canonical → ACK/NACK         | `h2h-ack-nack`                                                     |
| Canonical → Kafka event      | `h2h-observability` AuditEventPublisher                            |

***

## 7. Versioning

| Version | Changes                                        |
| ------- | ---------------------------------------------- |
| `1.0`   | Initial — payment, collection, ACK             |
| `1.1`   | Add `extensions` map, treasury fields (future) |

Breaking changes → new `modelVersion`; transforms declare supported versions.

***

## 8. Related Documents

* [43 Core Banking Integration API](/docs/43-core-banking-integration-api.md)
* [23 Finacle Integration](/docs/23-finacle-integration.md)
* [24 Transformation and Messaging](/docs/24-transformation-and-messaging.md)
* [25 ACK/NACK Framework](/docs/25-ack-nack-framework.md)
* [30 Database Schema Reference](/docs/30-database-schema-reference.md)
* [31 Error Code Catalog](/docs/31-error-code-catalog.md)


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://host2host.onibonje.com/docs/29-canonical-data-model.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
