Skip to main content

Deposit Transaction

Credit funds to a deposit account through various channels (teller, mobile, ATM, transfer).

Overview

Purpose: Process deposits that increase the account balance

Transaction Code: DEP / TELLER_DEP

Typical Use Cases:

  • Cash deposit at teller
  • Mobile/online banking deposit
  • ATM deposit
  • Third-party deposit
  • Transfer deposit from another account/bank
  • Payroll/bulk deposits

Transaction Flow

State Diagram

Entities Impacted

Scenario 1: Cash Deposit via Teller

Transaction: 5,000 cash deposit to account

TransactionImpactRecord {
transactionId: 12345,
transactionType: "Deposit",
transactionState: COMPLETED,
impactedEntities: [
// 1. DEPOSIT ACCOUNT - AvailableBalance
{
entityType: "DepositAccount",
entityId: 789,
entityKey: "ACC-2025-00789",
fieldName: "AvailableBalance",
oldValue: 10000,
newValue: 15000,
deltaAmount: +5000 // Customer can use immediately
},

// 2. DEPOSIT ACCOUNT - BookBalance
{
entityType: "DepositAccount",
entityId: 789,
fieldName: "BookBalance",
oldValue: 10000,
newValue: 15000,
deltaAmount: +5000 // Ledger balance updated
},

// 3. TELLER TILL - CashBalance
{
entityType: "TellerTill",
entityId: 45,
entityKey: "TILL-001-BRANCH-1",
fieldName: "CashBalance",
oldValue: 50000,
newValue: 55000,
deltaAmount: +5000 // Cash received into till
},

// 4. TELLER TILL - TransactionCount
{
entityType: "TellerTill",
entityId: 45,
fieldName: "TransactionCount",
oldValue: 23,
newValue: 24,
deltaAmount: +1
},

// 5. GL ACCOUNT - Cash
{
entityType: "GLAccount",
entityKey: "1010-CASH-IN-TILL",
fieldName: "DebitAmount",
deltaAmount: +5000 // DR: Increase asset
},

// 6. GL ACCOUNT - Customer Deposits
{
entityType: "GLAccount",
entityKey: "2100-CUSTOMER-DEPOSITS",
fieldName: "CreditAmount",
deltaAmount: +5000 // CR: Increase liability
}
]
}
```text
**Balance Changes**:
```text
Customer Account:
Before: AvailableBalance = 10,000, BookBalance = 10,000
After: AvailableBalance = 15,000, BookBalance = 15,000

Teller Till:
Before: CashBalance = 50,000
After: CashBalance = 55,000
```text
### Scenario 2: Transfer Deposit (from another bank)

**Transaction**: 20,000 transferred from external bank

```typescript
TransactionImpactRecord {
transactionId: 12346,
transactionType: "Deposit",
transactionState: COMPLETED,
impactedEntities: [
// DEPOSIT ACCOUNT impacts (same as above)

// SETTLEMENT ACCOUNT - Balance
{
entityType: "SettlementAccount",
entityId: 3,
entityKey: "SETTLEMENT-CENTRAL-BANK",
fieldName: "Balance",
oldValue: 1000000,
newValue: 1020000,
deltaAmount: +20000 // Funds received via settlement
},

// SETTLEMENT ACCOUNT - PendingCredits
{
entityType: "SettlementAccount",
entityId: 3,
fieldName: "PendingCredits",
oldValue: 20000,
newValue: 0,
deltaAmount: -20000 // Clear pending credit
},

// GL ENTRIES
{
entityType: "GLAccount",
entityKey: "1150-SETTLEMENT-ACCOUNT",
fieldName: "DebitAmount",
deltaAmount: +20000 // DR: Increase settlement asset
},
{
entityType: "GLAccount",
entityKey: "2100-CUSTOMER-DEPOSITS",
fieldName: "CreditAmount",
deltaAmount: +20000 // CR: Increase liability
}
]
}

```text
---

## Approval Workflow

### Auto-Approval Conditions

Deposit is auto-approved if **ALL** conditions met:
- Amount ≤ Auto-approval limit (from product config)
- Account is ACTIVE
- No fraud flags on account
- Channel has sufficient limit

### Manual Approval Required

If any condition fails:
1. Transaction state: PENDING
2. Notification sent to approvers
3. Amount may be placed on hold (optional)
4. Awaits approval decision

### Approval Actions

**On Approval**:
- Execute deposit (update balances)
- Post GL entries
- Change state to COMPLETED
- Send confirmation notification

**On Rejection**:
- Change state to REJECTED
- Release any holds
- Send rejection notification
- Audit trail created

---

## Account Activation

If deposit is made to an **APPROVED** (not yet ACTIVE) account:

**Before Deposit**:
```text
Account State: APPROVED
AvailableBalance: 0
BookBalance: 0
```text
**After Deposit**:
```text
Account State: ACTIVE ← Automatically activated
AvailableBalance: 5,000
BookBalance: 5,000
ActivationDate: 2025-12-28 10:30:00
```text
This is the **first transaction** that activates the account.

---

## Limits & Validation

### Pre-Transaction Checks

| Validation | Rule | Error If Failed |
|------------|------|-----------------|
| **Account State** | Must be ACTIVE or APPROVED | "Account is locked/dormant" |
| **Amount** | Must be > 0 | "Invalid amount" |
| **Single Transaction Limit** | Amount ≤ Tier limit | "Transaction limit exceeded" |
| **Maximum Balance** | Current + Amount ≤ Max balance | "Maximum balance exceeded" |
| **Daily Count** | Transactions today < Max count | "Daily transaction limit reached" |
| **Channel Limit** | Amount ≤ Channel limit | "Channel limit exceeded" |

### Limit Examples

```yaml
product_config:
tiers:
default:
depositTransactionLimit: 1000000 # Single transaction
maximumBalance: 50000000 # Account maximum
maxTransactionCountPerDay: 50 # Daily count

Scenario:

  • Account balance: 45,000,000
  • Deposit amount: 6,000,000
  • Maximum balance: 50,000,000

Result: ❌ REJECTED

Reason: "Maximum balance allowed is 50,000,000. 
Current: 45,000,000 + Deposit: 6,000,000 = 51,000,000"
```text
---

## Fee Calculation

Deposits may incur fees based on product configuration:

### Fee Configuration

```yaml
fees:
depositFees:
- name: "Cash Deposit Fee"
trigger: OnDeposit
calculationType: Percentage
percentage: 0.1
minimumAmount: 50
maximumAmount: 500
applicableChannels: ["TELLER", "BRANCH"]

Fee Calculation Example

Deposit: 100,000 via teller
Fee: 0.1% = 100 (but minimum is 50, maximum is 500)
Result: Fee = 100

Fee Deduction: Option 1: Deduct from deposit amount

Deposit Amount: 100,000
Fee: -100
Net Credit: 99,900
```text
Option 2: Separate fee transaction
```text
Deposit: +100,000 (full amount credited)
Fee: -100 (separate debit)
Net: 99,900
```text
---

## GL Posting

### Journal Entries - Cash Deposit

```text
Transaction: 5,000 cash deposit via teller

Entry:
Date: 2025-12-28
Reference: TXN-DEP-2025-001

DR: 1010 - Cash in Till 5,000.00
CR: 2100 - Customer Deposits 5,000.00
───────────────────────── ─────────
Total: 5,000.00
```text
### Journal Entries - Transfer Deposit

```text
Transaction: 20,000 transfer from external bank

Entry:
Date: 2025-12-28
Reference: TXN-DEP-2025-002

DR: 1150 - Settlement Account 20,000.00
CR: 2100 - Customer Deposits 20,000.00
───────────────────────── ─────────
Total: 20,000.00
```text
### With Fees

```text
Transaction: 100,000 deposit with 100 fee

Entry:
Date: 2025-12-28
Reference: TXN-DEP-2025-003

DR: 1010 - Cash in Till 100,000.00
CR: 2100 - Customer Deposits 99,900.00
CR: 4100 - Fee Income 100.00
───────────────────────── ──────────
Total: 100,000.00
```text
---

## API Usage

### Request

```http
POST /api/bpm/cmd
Content-Type: application/json
Authorization: Bearer {access_token}
```text
```json
{
"commandName": "InitiateDepositCommand",
"data": {
"accountEncodedKey": "ACC-2025-00789",
"channelCode": "TELLER",
"amount": 5000.00,
"transactionType": 0,
"notes": "Cash deposit from customer",
"serviceId": null,
"serviceDescription": null,
"isBackDated": false,
"backDateValueDate": null,
"isBookingDate": false,
"bookingDate": null,
"entryDate": "2025-12-28T10:30:00Z"
}
}
```text
### Response - Success

```json
{
"isSuccessful": true,
"statusCode": "00",
"message": "Deposit transaction completed successfully.",
"data": {
"transactionKey": "TXN-DEP-2025-001",
"accountNumber": "1234567890",
"accountOfficerEncodedKey": "AO-001",
"branchEncodedKey": "BRANCH-001",
"clientEncodedKey": "CLIENT-789",
"depositEncodedKey": "ACC-2025-00789",
"transactionState": "COMPLETED",
"newBalance": 15000.00
}
}
```text
### Response - Pending Approval

```json
{
"isSuccessful": true,
"statusCode": "00",
"message": "Deposit transaction pending approval.",
"data": {
"transactionKey": "TXN-DEP-2025-002",
"accountNumber": "1234567890",
"transactionState": "PENDING",
"requiresApproval": true,
"approvalReason": "Amount exceeds auto-approval limit"
}
}
```text
### Response - Error (Limit Exceeded)

```json
{
"isSuccessful": false,
"statusCode": "51",
"message": "The maximum balance allowed on the account is 50,000,000.00 NGN.",
"data": null
}
```text
---

## Narration Templates

Deposits use configurable narration templates:

### Customer Narration

Template:
```text
`Deposit of ${context.amount} via ${context.channelName}`
```text
Result:
```text
"Deposit of 5,000.00 via Teller"
```text
### Channel Narration

Template:
```text
`Deposit to ${context.accountNumber}`
```text
Result:
```text
"Deposit to 1234567890"
```text
### Configuring Templates

```yaml
narrationTemplates:
deposit:
customer: "`Deposit of ${context.amount} to ${context.accountNumber} via ${context.channelName}`"
channel: "`Cash deposit from customer ${context.clientName} to account ${context.accountNumber}`"
```text
---

## Error Codes

| Code | Message | Cause | Resolution |
|------|---------|-------|------------|
| `00` | Success | Transaction completed | N/A |
| `05` | Account locked | Account in LOCKED/DORMANT state | Unlock account first |
| `12` | Invalid amount | Amount ≤ 0 or invalid | Check amount |
| `14` | Invalid account | Account not found | Verify account key |
| `51` | Limit exceeded | Transaction or balance limit | Increase limit or split transaction |
| `57` | Account restricted | Account on PND or frozen | Remove restriction |
| `91` | System error | Database/system issue | Retry or contact support |

---

## Backdating & Booking Dates

Deposits support special date handling:

### Backdated Transaction

**Use Case**: Post transaction with past value date

```json
{
"isBackDated": true,
"backDateValueDate": "2025-12-26T00:00:00Z",
"entryDate": "2025-12-28T10:30:00Z"
}
```text
**Result**:
```text
EntryDate: 2025-12-28 (when entered)
ValueDate: 2025-12-26 (effective date)
BookDate: 2025-12-26 (posting date)
```text
### Custom Booking Date

**Use Case**: Post to specific GL period

```json
{
"isBookingDate": true,
"bookingDate": "2025-12-31T00:00:00Z"
}
```text
**Result**:
```text
EntryDate: 2025-12-28
ValueDate: 2025-12-28
BookDate: 2025-12-31 (custom GL date)
```text
---

## Concurrent Transaction Safety

Multiple deposits to same account are safe:

### Scenario

```text
Time 10:00 - Balance: 10,000

Time 10:01 - Deposit A: 5,000 (Teller 1)
├─ Read: Balance = 10,000
├─ Update: Balance = 15,000
└─ Version: 1 → 2

Time 10:01 - Deposit B: 3,000 (Teller 2)
├─ Read: Balance = 10,000 (old)
├─ Update: Balance = 13,000
└─ Version: 1 → 2 ❌ CONFLICT!

System detects version mismatch
├─ Retry Deposit B
├─ Read: Balance = 15,000 (current)
├─ Update: Balance = 18,000
└─ Version: 2 → 3 ✓

Final Balance: 18,000 ✓
```text
**Optimistic Locking** prevents lost updates!

---

## Best Practices

### For Tellers
1. Count cash carefully before processing
2. Verify customer identity
3. Confirm account number verbally
4. Print receipt for customer
5. Balance till at end of shift

### For Developers
1. Always validate account state
2. Check limits before execution
3. Use TransactionImpactRecord
4. Track all entity changes
5. Test concurrent scenarios
6. Handle all error codes

### For Operations
1. Monitor large deposits (AML)
2. Review pending approvals daily
3. Investigate failed transactions
4. Reconcile tills daily
5. Audit deposit patterns

---

## Related Operations

- **[Withdrawal](./withdrawal)**: Opposite operation (debit)
- **[Transfer](./transfer)**: Move between accounts
- **Reversal**: Undo completed deposit
- **Account Activation**: First deposit activates

---

## V2 API Commands

BankLingo V2 provides the **InitiateDepositCommand** for BPMCore integration.

### Command Overview

- **Command**: `InitiateDepositCommand`
- **Implementation**: `CB.Administration.Api/Commands/BPMCore/DepositWithdrawal/AdministrationCoreDepositTransactionCommandHandlers.cs`
- **Purpose**: Initiate deposit transactions with full approval workflow and impact tracking
- **BPM Integration**: Accepts parameters via `BpmUtil.GetPropertyValue()`
- **State Management**: PENDING → APPROVED → SETTLED

### Key Features

**Approval Workflow Integration**:
- Deposits requiring approval remain in PENDING state with available balance impact
- TransactionImpactTracker records all entity changes
- Approval/rejection handled via separate workflow commands

**Impact Tracking**:
- All account balance changes tracked via `TransactionImpactRecord`
- Delta-based tracking enables accurate concurrent transaction handling
- Impact records include: AccountId, EntityType, FieldName, OldValue, NewValue

**Concurrent Safety**:
- Optimistic locking with version checking
- Delta-based balance updates (not absolute values)
- Prevents lost updates in high-volume scenarios

**Till Integration** (Teller Context):
- When `tillId` provided, till balance automatically updated
- Cash deposits increase till balance
- Cheque deposits tracked as uncleared items

For detailed teller deposit workflows, see [Teller Deposit Transaction](../../teller-transactions/product/teller-deposit-technical-flow).

---

## Implementation Checklist

### Database
- [ ] TransactionImpactRecord table exists
- [ ] ImpactedEntity table exists
- [ ] CBSTransaction table includes State column
- [ ] DepositAccount includes Version column

### Code
- [ ] Impact tracking implemented
- [ ] Approval workflow implemented
- [ ] Fee calculation integrated
- [ ] GL posting automatic
- [ ] Narration templates used
- [ ] Limit validation complete
- [ ] Error handling comprehensive

### Testing
- [ ] Unit tests for validation
- [ ] Integration tests for full flow
- [ ] Concurrent deposit tests
- [ ] Approval workflow tests
- [ ] Limit breach tests
- [ ] Fee calculation tests

### Documentation
- [ ] Product config documented
- [ ] API endpoints documented
- [ ] Error codes listed
- [ ] Operator procedures created


---

## Developer Resources

For API implementation details, see:
- [Initiate Deposit API - Developer Guide](../../developer/initiate-deposit)
- [Deposit Transactions API Reference](../../developer/)
---

**Last Updated**: December 28, 2025
**Version**: 2.0
**Status**: Production Ready

**Next**: [Withdrawal Transaction →](./withdrawal)