All checks were successful
Auto Tag on Version Change / check-version (push) Successful in 6s
86 lines
4.1 KiB
Markdown
86 lines
4.1 KiB
Markdown
# Account Display Parser Architecture
|
|
|
|
## Overview
|
|
|
|
Each bank's API returns account data in different formats and uses different field names for balances, product types, and status. To keep screens bank-agnostic, each bank has a dedicated parser that translates raw `MibAccount` model data into a standard `AccountListDisplay` object. Screens consume only `AccountListDisplay` — they never inspect `bank` or `profileType` or apply bank-specific logic.
|
|
|
|
## Bank Discriminator — `MibAccount.bank`
|
|
|
|
All dispatchers route by `account.bank`, a string set explicitly by each login flow at account creation time:
|
|
|
|
| `bank` value | Set by |
|
|
|--------------|-------------------|
|
|
| `"MIB"` | `MibLoginFlow` |
|
|
| `"BML"` | `BmlLoginFlow` |
|
|
| `"FAHIPAY"` | `FahipayLoginFlow`|
|
|
|
|
`profileType` is a bank-internal value (e.g. MIB's numeric profile ID, or BML's `"BML_PREPAID"`) and is **never** used for bank routing. Card-type checks within BML still use `profileType` (`"BML_PREPAID"` / `"BML_CREDIT"`).
|
|
|
|
`cifType` (MIB only) is the human-readable profile category name returned by the `operatingProfiles` API (e.g. `"Individual"`, `"Sole Propr"`). It is stored on `MibAccount` and surfaced in the accounts list section header and settings. It is **never hardcoded** in the app.
|
|
|
|
## Standard Output Model
|
|
|
|
```kotlin
|
|
// util/AccountListDisplay.kt
|
|
data class AccountListDisplay(
|
|
val name: String, // account or card display name
|
|
val number: String, // account/card number
|
|
val typeLabel: String, // human-friendly product type (e.g. "Savings", "Visa Platinum")
|
|
val balance: String, // formatted balance string (e.g. "MVR 1,234.56")
|
|
val isCard: Boolean, // true → use card layout; false → use account layout
|
|
val cardBrandIcon: Int, // drawable res for card brand logo (Visa / Mastercard / Amex)
|
|
val statusLabel: String? // null = active; non-null = shown as status label (e.g. "Inactive")
|
|
)
|
|
```
|
|
|
|
## Dispatcher
|
|
|
|
```kotlin
|
|
// util/AccountListParser.kt
|
|
AccountListParser.from(account: MibAccount): AccountListDisplay?
|
|
```
|
|
|
|
Routes to the correct parser based on `account.bank`. Returns `null` for unknown banks — never falls back to a specific bank.
|
|
|
|
| `account.bank` | Parser |
|
|
|----------------|-------------------------|
|
|
| `"BML"` | `BmlDashboardParser` |
|
|
| `"FAHIPAY"` | `FahipayAccountParser` |
|
|
| `"MIB"` | `MibAccountParser` |
|
|
| anything else | `null` |
|
|
|
|
## Bank Parsers
|
|
|
|
### BML — `util/bmlapi/BmlDashboardParser`
|
|
|
|
Handles both CASA accounts and prepaid/credit cards.
|
|
|
|
- **CASA balance**: uses `ledgerBalance` (working balance) — mapped to `account.currentBalance`
|
|
- **Card balance**: uses `availableBalance` (available limit from `cardBalance.AvailableLimit`)
|
|
- **Card brand**: resolved from product name (`VISA` / `MASTERCARD` / `AMEX`)
|
|
- **Status**: cards with `statusDesc != "Active"` surface `statusLabel`; active cards return `null`
|
|
|
|
### MIB — `util/mibapi/MibAccountParser`
|
|
|
|
- **Balance**: `availableBalance` from the MIB API directly
|
|
- Known product names (`SAVING ACCOUNT`, `CURRENT ACCOUNT`) mapped to short labels
|
|
- `cifType` (e.g. `"Individual"`, `"Sole Propr"`) comes from `MibProfile.cifType`, stored on `MibAccount`, displayed in section headers
|
|
|
|
### Fahipay — `util/fahipayapi/FahipayAccountParser`
|
|
|
|
- Single wallet account per user; `accountTypeName` is always `"Digital Wallet"`
|
|
- **Balance**: `availableBalance`
|
|
|
|
## Adding a New Bank
|
|
|
|
1. Create `util/<bankname>api/<Bank>AccountParser.kt` with a `displayData(account: MibAccount): AccountListDisplay` function
|
|
2. Set `bank = "<BANKNAME>"` in the new login flow when creating `MibAccount` objects
|
|
3. Add a `when` branch in `AccountListParser.from()` (and other dispatchers) for the new bank value
|
|
4. No changes needed in any screen or adapter
|
|
|
|
## Usage in Screens
|
|
|
|
`AccountsAdapter` calls `AccountListParser.from(account)` once per item (skipping `null` results) and binds the resulting `AccountListDisplay` directly. The adapter has zero bank-specific logic.
|
|
|
|
The transfer screen dropdown (`TransferFragment`) also uses `AccountListParser.from(acc)?.balance` for the source account balance display.
|