---
name: Default Accounts — Treasury / Banking / Payment-Method GL Accounts
description: >
  Every "default account" setting (a setting whose stored value is a GL account id used
  automatically when posting journal entries) in the TREASURY / BANKING / PAYMENT area:
  POS cash/card/default receiving accounts, the accounting checks-received/issued
  intermediate accounts, the LIS cash account, plus how treasuries (PettyCash) and
  payment methods (LabPaymentMethod) carry per-INSTANCE GL account ids that bypass the
  settings table. Maps key → AR/EN label → purpose → definition file:line → consumption
  site → whether it is already on the /setup Default-Accounts page.
updated: 2026-06-18
---

# Treasury / Banking / Payment-Method Default Accounts

This topic covers the **money-in / money-out plumbing**: the GL accounts a payment is
*debited to* when cash/card/check is received, the intermediate accounts for checks, and
the two mechanisms by which the receiving account is resolved at posting time:

1. **Settings-based** default accounts (`*_account_id` setting keys) — what this topic and
   the `/setup` page are about.
2. **Per-instance GL account ids** carried on the **treasury (`PettyCash`)** and
   **payment-method (`LabPaymentMethod`)** rows themselves — a parallel, per-row mechanism
   that is **separate from the settings table** (see §3). This is the LIS gotcha that
   broke elmadina payments (methods held a stale GL id while settings were already
   remapped).

> "Default account" here = a setting whose stored **value is a GL account id** that the
> system uses automatically when posting a journal entry.

---

## 1. Settings-based default accounts (this area)

| # | Setting key | EN label | AR label | Module | Value type | Definition (file:line) | On /setup? |
|---|-------------|----------|----------|--------|-----------|------------------------|:----------:|
| 1 | `pos.cash_receiving_account_id` | Cash Receiving Account | حساب استلام الكاش (الخزينة) | pos | integer | `Modules/Core/database/seeders/SettingDefinitionSeeder.php:1974` | ❌ |
| 2 | `pos.card_receiving_account_id` | Card/Network Receiving Account | حساب استلام الشبكة (حساب وسيط) | pos | integer | `…/SettingDefinitionSeeder.php:1990` | ❌ |
| 3 | `pos.default_receiving_account_id` | Default Receiving Account | حساب الاستلام العام | pos | integer | `…/SettingDefinitionSeeder.php:2006` | ❌ |
| 4 | `pos.default_receiving_account_type` | Default Receiving Account Type | نوع حساب الاستلام الافتراضي | pos | enum (`petty_cash`\|`bank_account`) | `…/SettingDefinitionSeeder.php:2022` | ❌ |
| 5 | `accounting.checks_received_account_id` | Checks Received Intermediate Account | حساب الشيكات المُستلَمة الوسيط | accounting | integer | `…/SettingDefinitionSeeder.php:325` | ❌ |
| 6 | `accounting.checks_issued_account_id` | Checks Issued Intermediate Account | حساب الشيكات المُصدَرة الوسيط | accounting | integer | `…/SettingDefinitionSeeder.php:309` | ❌ |
| 7 | `lis.cash_account_id` | Cash Account | حساب النقد | lis | integer | `Modules/LIS/database/seeders/LabSettingDefinitionSeeder.php:422` | ❌ |

Notes:
- **#4 `pos.default_receiving_account_type`** is *not* itself a GL-account-id setting (its
  value is the enum `petty_cash`/`bank_account`), but it is listed because it qualifies
  #3 (it tells the POS what kind of account the default receiving account is). Document it
  alongside the receiving accounts.
- All seven default to `null`, scope `company` — i.e. each company must pick them; the
  system does **not** auto-provision them (unlike the per-instance treasury accounts in §3,
  which `AutoAccountService` creates behind the scenes).

### Purpose & consumption — POS receiving accounts (#1–#4)

These three accounts are the **debit side** of a POS sale payment (the asset that receives
the money). Resolution happens in `POSSaleController::resolveReceivingAccount()`:

`Modules/POS/app/Http/Controllers/POSSaleController.php:180-204`

```php
$accountId = match ($method) {
    'cash'  => $settings->get('pos.cash_receiving_account_id', $companyId),   // #1
    'card'  => $settings->get('pos.card_receiving_account_id', $companyId),   // #2
    'check' => $settings->get('pos.cash_receiving_account_id', $companyId),   // #1 (check shares cash acct)
    default => null,
};
if (! $accountId) $accountId = $settings->get('pos.default_receiving_account_id', $companyId); // #3 fallback
if (! $accountId) $accountId = $settings->get('sales.cash_account_id', $companyId);            // legacy fallback
```

- **cash** → `pos.cash_receiving_account_id` (the treasury/cash box). Description hints
  "e.g. petty cash / treasury".
- **card / network** → `pos.card_receiving_account_id`, an **intermediary** account: money
  in transit from the payment provider to the bank (settled later).
- **check** → reuses `pos.cash_receiving_account_id`.
- Anything else / unset → `pos.default_receiving_account_id` (#3), then legacy
  `sales.cash_account_id`.
- `#4 pos.default_receiving_account_type` flags whether #3 is a petty-cash box or a bank
  account (used when the POS needs to know how to treat the fallback account).

### Purpose & consumption — checks intermediate accounts (#5–#6)

Two-step check lifecycle uses an intermediate (clearing) account so the bank/cash isn't
touched until the check actually clears:

- **#5 `accounting.checks_received_account_id`** — *asset* account **debited on check
  receipt**, **credited when the bank collects** the check. Default code typically `1103`.
  Consumed in `Modules/Accounting/app/Actions/CollectCheck.php:30`
  (`$intermediateAccountId = (int) $this->settings->get('accounting.checks_received_account_id', …)`).
- **#6 `accounting.checks_issued_account_id`** — *liability* account **credited on check
  issue**, **debited when the check clears** the bank. Default code typically `2103`.
  Consumed in `Modules/Accounting/app/Actions/CashCheck.php:32`
  (`$intermediateAccountId = (int) $this->settings->get('accounting.checks_issued_account_id', …)`).

### Purpose & consumption — LIS cash account (#7)

- **#7 `lis.cash_account_id`** — the lab's cash account, used as a fallback for lab cash
  outflows. Consumed in
  `Modules/LIS/app/Services/DoctorCommissionService.php:384-385`:
  ```php
  $cashAccountId = $this->settings->get('lis.cash_account_id', $companyId)
      ?? $this->settings->get('accounting.default_cash_account_id', $companyId);
  ```
  (i.e. lab cash setting → core default-cash setting fallback). For inbound lab patient
  payments the receiving account is **NOT** taken from this setting; it comes from the
  per-instance mechanism in §3 (the payment carries its own `receiving_account_id`).

---

## 2. Other treasury-area settings referenced in code (NOT in this module's seeders)

These appear in the consumption code above but are **defined in other agents' areas** —
listed here only for cross-reference; do **not** re-document them in this file:

| Setting key | Where seen | Owning area |
|-------------|-----------|-------------|
| `sales.cash_account_id` | POSSaleController:200 (legacy fallback) | Sales settings |
| `accounting.default_cash_account_id` | DoctorCommissionService:385 (fallback) | Accounting / core defaults |
| `accounting.cash_parent_account` (=`1101`) | LabTreasuryController:107 | parent-account config (not a leaf GL default) |
| `accounting.bank_parent_account` (=`1102`) | LabTreasuryController:402 | parent-account config |
| `lis.petty_expense_account_id` / `lis.petty_funding_account_id` | LabTreasuryController:269-282 (auto-provisioned counterparts) | LIS petty-cash counterparts |

---

## 3. Per-INSTANCE GL account ids — the parallel mechanism (CRITICAL gotcha)

Treasuries and payment methods do **not** read a setting to know their GL account. Each
**row** stores its own `account_id`. This is separate from, and overrides, the settings in
§1. Transferring a company's config (e.g. moonui → elmadina) must remap these per-row ids,
or payments post to a non-existent account (404 / draft invoice).

### 3a. Treasury (cash box) = `Accounting\PettyCash`

LIS labs manage cash boxes via `LabTreasuryController` — a thin wrapper over the Accounting
`PettyCash` model (`Modules/LIS/app/Http/Controllers/LabTreasuryController.php`).

- **Creating a treasury** auto-links a fresh GL sub-account under the cash parent (`1101`)
  via `AutoAccountService::createChildAccount()` — the lab never picks an account:
  `LabTreasuryController::storeTreasury()` lines **107-123** (`$account_id = $account?->id`).
- **Creating a bank** auto-links a sub-account under the bank parent (`1102`):
  `storeBank()` lines **402-417**.
- The stored `petty_cash.current_balance` is **not** updated by lab payments; the live
  balance is derived from the linked GL account's journal lines (debit − credit):
  `treasuries()` lines **76-87**.
- Per-branch cash boxes carry a `branch_id` (lines 102, 120) — routing resolves the
  cashier's branch box from the logged-in user's `primaryBranch()` (§3c).

So each cash box / bank = one `PettyCash` / `BankAccount` row, each with its own
`account_id` GL leaf. **There is no single "treasury account" setting** — the treasury
*is* the account.

### 3b. Payment method = `LIS\LabPaymentMethod`

`Modules/LIS/app/Models/LabPaymentMethod.php` — table `lab_payment_methods`
(`Modules/LIS/database/migrations/2026_06_03_000000_create_lab_payment_methods_table.php`).

Columns (migration lines 17-32): `key`, `label_en`, `label_ar`, `icon`,
**`account_id` (nullable — linked GL/treasury account)**, `is_cash`, `is_active`,
`sort_order`, unique `(company_id, key)`. Fillable includes `account_id`
(`LabPaymentMethod.php:16-19`).

Default seeded keys: `cash`, `visa`, `tamara`, `tabby`, `bank_transfer`
(`LabPaymentMethod.php:35`). Each row's `account_id` is the GL account that a payment via
that method is debited to. The method's `account_id` is editable from the API
(`LabPaymentMethodController.php:86` validates `account_id` nullable integer).

> 🔴 **Transfer gotcha (elmadina, 2026-06-17):** payments failed because
> `lab_payment_methods.account_id` still held **moonui's** GL ids (65 / 228-231 → 404 on
> elmadina) even though the `lis.*` *settings* were already remapped. Payment-methods and
> treasuries carry per-instance GL account ids that must be remapped on transfer,
> **separate** from the settings. Fix = recreate cash boxes via `POST /lis/treasuries`
> (auto-creates a GL child under `1101`) + repoint methods via
> `PUT /lis/payment-methods/{id}`.

### 3c. How the receiving account reaches a lab payment

For an **inbound patient payment**, the debit (receiving) account is **chosen by the
cashier at collect time** and stored on the payment row, then used verbatim when posting —
it does NOT come from a setting:

1. **Routing endpoint** builds method → account map:
   `LabPaymentController::routing()` (`…/LabPaymentController.php:42-104`):
   - `method_accounts`: each active method's `account_id` (lines 55-60).
   - `accounts`: live treasury GL accounts from `PettyCash` (lines 62-74).
   - `resolved`: per-branch override — `is_cash` methods route to the cashier's
     **branch cash box** (`branchCash->account_id`) resolved from
     `$user->primaryBranch()` (lines 76-88, 101).
2. **Store** validates `receiving_account_id` as `exists:accounts,id` (required):
   `Modules/LIS/app/Http/Requests/StoreLabPaymentRequest.php:28`. It is persisted on the
   payment (`LabPayment.php:55`, relation at `:106`).
3. **Post** debits exactly that account:
   `Modules/LIS/app/Actions/PostLabPayment.php:28,35`
   (`$receivingAccountId = (int) $payment->receiving_account_id;` → first JE line debit),
   crediting the partner/insurance AR account (lines 75-102). External-lab payments behave
   the same: `RecordExternalLabPayment.php:68,93`.

**Net:** the lab path uses the per-instance `account_id` (treasury / payment-method) →
payment.`receiving_account_id` → JE debit. The POS path uses the §1 settings. Both end up
debiting a cash/bank/intermediary GL account.

---

## 4. /setup Default-Accounts page — current coverage

The first-run wizard step **STEP_DEFAULTS** (`SETUP.STEP_DEFAULTS`) saves exactly **seven**
`accounting.default_*` settings — none of which are the keys in §1. It auto-picks by GL
code then `POST`s them:

`src/app/features/setup/setup-wizard.component.ts:656-712`

| Setting written by /setup | Auto-picked code(s) | file:line |
|---------------------------|---------------------|-----------|
| `accounting.default_cash_account` | `1101` | setup-wizard.component.ts:665,680 |
| `accounting.default_bank_account` | `1102` | :666,685 |
| `accounting.default_client_account` (receivable) | `1103` | :667,690 |
| `accounting.default_supplier_account` (payable) | `2101` | :668,695 |
| `accounting.default_expense_account` | `5201`/`5101` | :669,700 |
| `accounting.default_revenue_account` | `41` | :670,705 |
| `accounting.default_check_account` | `1104` | :671,710 |

**Therefore: ALL 7 treasury/payment keys in §1 are `on_setup_page = false`.** The page
covers only the generic `accounting.default_*` set (cash/bank/المدينون/الدائنون/expense/
revenue/notes-check), keyed by hard-coded GL codes — it does **not** touch the
`pos.*_receiving_*`, `accounting.checks_received/issued_account_id`, or `lis.cash_account_id`
settings, nor the per-instance treasury/payment-method `account_id` rows.

> **Extension implication for the owner's ask:** to surface treasury/payment defaults on
> /setup, add the §1 keys (POS receiving x3 + checks x2 + lis.cash). The per-instance ids
> in §3 are a different shape (rows, auto-provisioned) and would belong on the existing
> Treasuries / Payment-Methods management screens, not as single-value settings.

---

## Quick file:line index

| What | File:line |
|------|-----------|
| POS cash receiving def | `Modules/Core/database/seeders/SettingDefinitionSeeder.php:1974` |
| POS card receiving def | `…SettingDefinitionSeeder.php:1990` |
| POS default receiving def | `…SettingDefinitionSeeder.php:2006` |
| POS default receiving type def | `…SettingDefinitionSeeder.php:2022` |
| Checks issued def | `…SettingDefinitionSeeder.php:309` |
| Checks received def | `…SettingDefinitionSeeder.php:325` |
| LIS cash account def | `Modules/LIS/database/seeders/LabSettingDefinitionSeeder.php:422` |
| POS receiving consumption | `Modules/POS/app/Http/Controllers/POSSaleController.php:180-204` |
| Check collect consumption | `Modules/Accounting/app/Actions/CollectCheck.php:30` |
| Check cash/clear consumption | `Modules/Accounting/app/Actions/CashCheck.php:32` |
| LIS cash consumption | `Modules/LIS/app/Services/DoctorCommissionService.php:384-385` |
| Treasury (PettyCash) create + auto GL | `Modules/LIS/app/Http/Controllers/LabTreasuryController.php:107-123` |
| Bank create + auto GL | `…/LabTreasuryController.php:402-417` |
| Payment-method model (account_id) | `Modules/LIS/app/Models/LabPaymentMethod.php:16-19,35` |
| Payment-method table | `Modules/LIS/database/migrations/2026_06_03_000000_create_lab_payment_methods_table.php:17-32` |
| Payment routing (method→account) | `Modules/LIS/app/Http/Controllers/LabPaymentController.php:42-104` |
| Lab payment receiving_account_id (store) | `Modules/LIS/app/Http/Requests/StoreLabPaymentRequest.php:28` |
| Lab payment posting (debit receiving) | `Modules/LIS/app/Actions/PostLabPayment.php:28,35` |
| /setup defaults written | `src/app/features/setup/setup-wizard.component.ts:656-712` |
