---
name: POS Default Accounts
description: Every default GL-account setting used by the POS (Point of Sale) module when auto-posting POS sales — what each key is, its AR/EN label, where it is defined, where it is consumed at posting time, and whether it is already exposed on the first-run /setup "Default Accounts" page. Includes the important fact that POS reuses the Sales-module accounts for revenue/tax/discount/COGS/receivable.
updated: 2026-06-18
---

# POS Default Accounts

## TL;DR / Executive summary

- The POS module defines **only 3 GL-account settings of its own**, and they are all for the
  **payment (money-received) leg** of a POS sale:
  `pos.cash_receiving_account_id`, `pos.card_receiving_account_id`, and the fallback
  `pos.default_receiving_account_id`.
- POS does **NOT** define its own revenue, tax, discount, COGS, inventory, receivable, change,
  rounding, or over/short accounts. A POS sale is posted by reusing the **Sales module** posting
  actions (`PostSalesInvoice` + `PostSalesPayment`), so **all of those accounts come from the
  `sales.*` settings** (revenue, tax payable, discount, COGS, inventory, receivable). See
  [Accounts POS reuses](#accounts-pos-reuses-from-sales) below.
- There is **no "change due", "over/short", "cash variance", or "rounding" GL account** anywhere
  in POS. Session close records the cash variance as data only (`expected_balance` vs
  `closing_balance`) and posts **no** journal entry.
- **None** of the POS account settings are currently on the `/setup` "Default Accounts" page
  (`setup-wizard.component.ts`). The wizard only writes 6 generic `accounting.default_*` keys.

---

## 1. POS-owned default-account settings

All POS settings are defined in the Core seeder
`/home/moonui/moon-erp-be/Modules/Core/database/seeders/SettingDefinitionSeeder.php`
(POS block starts at line **1940**, comment `// ── POS ──`). `module => 'pos'`,
`scope => 'company'`, `display_group => 'pos_general'`.

| Key | Label EN | Label AR | Type | Purpose (when posting) | Definition | On `/setup`? |
|-----|----------|----------|------|------------------------|-----------|--------------|
| `pos.cash_receiving_account_id` | Cash Receiving Account | حساب استلام الكاش (الخزينة) | integer (GL account id) | **DR account** for the *cash* payment leg of a POS sale (cash drawer / treasury / petty cash). Also used for **`check`** payments (check maps to the cash account). | `SettingDefinitionSeeder.php:1974` | No |
| `pos.card_receiving_account_id` | Card/Network Receiving Account | حساب استلام الشبكة (حساب وسيط) | integer (GL account id) | **DR account** for the *card/network* payment leg — an **intermediary** account holding money in transit from the payment provider to the bank. | `SettingDefinitionSeeder.php:1990` | No |
| `pos.default_receiving_account_id` | Default Receiving Account | حساب الاستلام العام | integer (GL account id) | **Fallback** receiving account used when the method-specific account (cash/card) is not configured. | `SettingDefinitionSeeder.php:2006` | No |

### Related POS settings that are NOT GL-account ids (for completeness, do not add to Default-Accounts page)

| Key | Label EN | Type | Note | Definition |
|-----|----------|------|------|-----------|
| `pos.default_receiving_account_type` | Default Receiving Account Type | enum `petty_cash` \| `bank_account` (default `petty_cash`) | Classifies the default receiving account; **not** an account id. Not consumed by `POSSaleController` posting today. | `SettingDefinitionSeeder.php:2022` |
| `pos.default_customer_id` | Default Cash Customer | integer (partner id) | Walk-in cash customer; not a GL account. | `SettingDefinitionSeeder.php:1942` |
| `pos.default_warehouse_id` | Default Warehouse | integer (warehouse id) | Stock deduction warehouse; not a GL account. | `SettingDefinitionSeeder.php:1958` |

---

## 2. Where the POS receiving accounts are consumed

File: `/home/moonui/moon-erp-be/Modules/POS/app/Http/Controllers/POSSaleController.php`

- `store()` builds the invoice (status `Approved`), posts it via `PostSalesInvoice` (line **117**),
  then for each payment resolves the receiving account and posts via `PostSalesPayment` (line **153**).
- `resolveReceivingAccount()` — **lines 180-204** — is the entire account-resolution logic:

| Step | Code | Setting used |
|------|------|--------------|
| Method-specific | `POSSaleController.php:187` | `pos.cash_receiving_account_id` (method `cash`) |
| Method-specific | `POSSaleController.php:188` | `pos.card_receiving_account_id` (method `card`) |
| Method-specific | `POSSaleController.php:189` | `pos.cash_receiving_account_id` (method `check` → reuses cash) |
| Fallback #1 | `POSSaleController.php:195` | `pos.default_receiving_account_id` |
| Fallback #2 (legacy) | `POSSaleController.php:200` | `sales.cash_account_id` |

If all of the above resolve to null, the sale throws
`"No receiving account configured for payment method: {method}. Configure POS settings first."`
(`POSSaleController.php:135`). The resolved id is stored on the payment as
`receiving_account_id` (`POSSaleController.php:148`) and becomes the **debit** side of the
payment journal entry created by `PostSalesPayment`.

**Resolution order (effective):**
`pos.<method>_receiving_account_id` → `pos.default_receiving_account_id` → `sales.cash_account_id`.

---

## 3. Accounts POS reuses from Sales

A POS sale is just a Sales invoice + Sales payment, posted through the Sales actions
`Modules\Sales\Actions\PostSalesInvoice` and `Modules\Sales\Actions\PostSalesPayment`
(imported at `POSSaleController.php:13-14`). Therefore the **invoice/revenue side** of POS
accounting is driven entirely by `sales.*` settings — POS has no duplicate of these:

| Reused setting (Sales module) | Role in a POS sale | Consumed at |
|-------------------------------|--------------------|-------------|
| `sales.revenue_account_id` | CR revenue for sold items | `Modules/Sales/app/Actions/PostSalesInvoice.php:91` |
| `sales.tax_payable_account_id` | CR output VAT/tax | `PostSalesInvoice.php:92` |
| `sales.discount_account_id` | DR discount given | `PostSalesInvoice.php:93` |
| `sales.cogs_account_id` | DR cost of goods sold | `PostSalesInvoice.php:173` |
| `sales.inventory_account_id` (then `purchases.inventory_account_id`) | CR inventory on stock deduction | `PostSalesInvoice.php:300, 307` |
| `sales.receivable_account_id` | DR receivable (credit-customer leg) | `PostSalesInvoice.php:423` |
| `sales.cash_account_id` | Last-resort POS receiving account fallback | `POSSaleController.php:200` |

> Implication for the Default-Accounts page: POS does **not** need its own revenue/tax/discount/
> COGS/receivable rows — those belong to the **Sales** area. The only POS-specific additions are
> the 3 receiving accounts (cash / card / default).

---

## 4. What POS deliberately does NOT have

- **No change-due account** — POS does not post change as a GL line.
- **No over/short (cash variance) account** — `POSSessionController::close()` records
  `expected_balance` vs `closing_balance` and per-method `expected_amount`/`actual_amount`
  (`POSSessionPayment`), but creates **no journal entry**
  (`/home/moonui/moon-erp-be/Modules/POS/app/Http/Controllers/POSSessionController.php:150-185`).
  Variance is reporting data only.
- **No rounding account.**
- **No terminal-level or session-level account override** — accounts resolve at company scope only.

If the owner later wants over/short or change posting, those accounts would be **net-new**
(no setting key, no consumer code exists today).

---

## 5. `/setup` "Default Accounts" page status

File: `/home/moonui/public_html/moon-erp/src/app/features/setup/setup-wizard.component.ts`

- The wizard writes only these 6 generic keys (lines **678-707**), auto-detected from the
  chart of accounts (lines **665-670**):
  `accounting.default_cash_account`, `accounting.default_bank_account`,
  `accounting.default_receivable_account`, `accounting.default_payable_account`,
  `accounting.default_expense_account`, `accounting.default_revenue_account`.
- **No `pos.*` key is present.** To extend the page for POS, add rows for the 3 POS receiving
  accounts (`pos.cash_receiving_account_id`, `pos.card_receiving_account_id`,
  `pos.default_receiving_account_id`). The enum `pos.default_receiving_account_type` and the
  non-account defaults (`pos.default_customer_id`, `pos.default_warehouse_id`) should **not** go
  on the Default-Accounts page.

---

## 6. File reference index

| Path | What |
|------|------|
| `/home/moonui/moon-erp-be/Modules/Core/database/seeders/SettingDefinitionSeeder.php` | POS setting definitions, lines 1940-2036 |
| `/home/moonui/moon-erp-be/Modules/POS/app/Http/Controllers/POSSaleController.php` | POS sale posting + `resolveReceivingAccount()` (180-204) |
| `/home/moonui/moon-erp-be/Modules/POS/app/Http/Controllers/POSSessionController.php` | Session close, cash variance (no JE), lines 150-185 |
| `/home/moonui/moon-erp-be/Modules/Sales/app/Actions/PostSalesInvoice.php` | Revenue/tax/discount/COGS/inventory/receivable accounts POS reuses |
| `/home/moonui/public_html/moon-erp/src/app/features/setup/setup-wizard.component.ts` | Current `/setup` Default-Accounts page (6 generic keys) |
