# Financial Statements

To programmatically verify a financial statement, you need to combine OCR (Optical Character Recognition), Document Parsing, and Mathematical Validation.

In an AdonisJS environment, you shouldn't try to build the OCR engine yourself. Instead, use a specialized service that returns structured JSON, then perform the "sanity check" logic in your backend.

***

### 1. The Extraction Pipeline

For a financial relay or KYC system, you need more than just text; you need Key-Value pairs (e.g., "Total Balance": 5000.00).

#### Recommended Tools:

* AWS Textract (Queries/AnalyzeExpense): Specifically designed for invoices and bank statements. It identifies tables and totals automatically.

  <a class="button secondary"></a><a class="button secondary"></a>
* Google Document AI: Excellent for recognizing the difference between a "Date" and an "Amount."
* Azure Form Recognizer: Very strong at identifying table structures in PDFs.

  <a class="button secondary"></a>

***

### 2. Programmatic Verification Logic

Once you have the JSON data from the OCR service, your AdonisJS service needs to run a "Summation Check."

#### The "Add Up" Logic (Sample Service)

TypeScript

```
// app/Services/FinanceValidatorService.ts
export default class FinanceValidatorService {
  public async verifySum(extractedData: any) {
    // 1. Target the 'Transactions' table from the OCR JSON
    const transactions = extractedData.tables[0].rows;
    const reportedTotal = extractedData.fields.find(f => f.key === 'TOTAL_BALANCE')?.value;

    // 2. Calculate the sum manually
    let calculatedSum = 0;
    transactions.forEach(row => {
      // Clean the string (remove currency symbols and commas)
      const amount = parseFloat(row.amount.replace(/[^0-9.-]+/g, ""));
      calculatedSum += amount;
    });

    // 3. Compare with a small tolerance for rounding
    const difference = Math.abs(calculatedSum - reportedTotal);
    const isConsistent = difference < 0.01;

    return {
      isConsistent,
      reportedTotal,
      calculatedSum,
      difference,
      error: !isConsistent ? "The sum of transactions does not match the stated total." : null
    };
  }
}
```

***

### 3. High-Risk Areas for Tampering

When a fraudster edits a statement, they often change the "Total" at the bottom but forget to adjust one of the individual transaction lines, or vice-versa.

* Balance Carry-forward: Check if `Previous Balance + Total Credits - Total Debits = New Balance`.
* Transaction Density: Scammers often delete transactions to hide gambling or high-risk spending. Look for "Gaps" in dates or missing sequence numbers if the bank provides them.

  <a class="button secondary"></a>
* Rounding Errors: Automated banking systems are perfect. If your manual calculation shows a difference of `$0.01`, it could be a rounding strategy, but if it's `$0.05` or more, the document has been manually edited.

***

### 4. Visualizing the Validation in Vue

In your KYC dashboard, you should highlight the specific rows that caused the "Summation Error."

Code snippet

```
<template>
  <div class="p-4 border rounded" :class="audit.isConsistent ? 'border-green-500' : 'border-red-500'">
    <h3 class="font-bold">Mathematical Audit</h3>
    <div class="grid grid-cols-2 gap-4 mt-2">
      <div>
        <p class="text-sm text-gray-500">Stated Total</p>
        <p class="text-lg">{{ audit.reportedTotal }}</p>
      </div>
      <div>
        <p class="text-sm text-gray-500">Calculated Sum</p>
        <p class="text-lg" :class="{'text-red-600 font-bold': !audit.isConsistent}">
          {{ audit.calculatedSum }}
        </p>
      </div>
    </div>
    <p v-if="!audit.isConsistent" class="mt-2 text-red-600 text-sm italic">
      ⚠️ {{ audit.error }}
    </p>
  </div>
</template>
```

***

### 5. Why this is the "Best Way"

By doing this programmatically:

1. Efficiency: Your analysts don't need a calculator.
2. Scalability: You can process 1,000 KYB applications an hour.
3. Accuracy: Human eyes miss `$1,200.00` vs `$1,200.80` errors; your AdonisJS service won't.

Would you like me to show you how to connect this to an AWS Textract implementation so you can start pulling the actual data from a PDF?
