---
name: manufacturing-accounts
description: Every default GL account setting for the Manufacturing / Production module (WIP, finished goods, scrap, applied labor/overhead absorption, cost variance, toll clearing, customer advances) — keys, AR/EN labels, definition file:line, where each is consumed when posting journal entries, and whether it is on the first-run /setup Default-Accounts page. Reference for extending /setup to cover MFG accounts.
updated: 2026-06-18
---

# Manufacturing / Production — Default Accounts

## TL;DR
Production has **8 default-account settings** (keys ending in `_account_id`). All live in the **`production.*`** namespace, are **company-scoped integers**, default to **`null`**, and are **NOT** on the first-run `/setup` page — they are resolved **lazily on first posting** by `ProductionAccountResolver`, which find-or-creates a child detail account under a fixed Chart-of-Accounts parent and persists the new id back into the setting.

- **Definitions:** `Modules/Production/database/seeders/ProductionSettingDefinitionSeeder.php`
- **Resolver (the single source of lazy creation):** `Modules/Production/app/Services/ProductionAccountResolver.php`
- **/setup page (FE):** `src/app/features/setup/setup-wizard.component.ts` — writes only **7 `accounting.*`** keys (cash, bank, client, supplier, expense, revenue, check). **Zero** production keys. So **none** of the 8 below appear on `/setup` today.

> Because every account is auto-created on first posting, an admin never *has* to set these. But the owner wants them exposed on `/setup` so the chosen accounts are explicit/correct from day one instead of whatever the resolver auto-names. The resolver's lazy `set()` means: once posting has happened, the setting will already hold an id (so the future `/setup` UI should read the current value and let the admin re-point it).

---

## The 8 default-account settings

| # | Key | EN label | AR label | CoA parent (auto-create) | On /setup? |
|---|-----|----------|----------|--------------------------|------------|
| 1 | `production.wip_account_id` | Work-In-Progress Account | حساب الإنتاج تحت التشغيل | `11` Current Assets | No |
| 2 | `production.fg_account_id` | Finished Goods Account | حساب المنتجات التامة | `11` Current Assets | No |
| 3 | `production.scrap_account_id` | Production Scrap Account | حساب هالك الإنتاج | `52` Operating Expenses | No |
| 4 | `production.labor_applied_account_id` | Labor Applied Account | حساب العمالة المحملة | `21` Current Liabilities | No |
| 5 | `production.overhead_applied_account_id` | Overhead Applied Account | حساب التكاليف غير المباشرة المحملة | `21` Current Liabilities | No |
| 6 | `production.cost_variance_account_id` | Production Cost Variance Account | حساب انحراف تكلفة الإنتاج | `52` Operating Expenses | No |
| 7 | `production.toll_clearing_account_id` | Toll Clearing Account | حساب تسوية التصنيع لدى الغير | `11` Current Assets | No |
| 8 | `production.customer_advance_account_id` | Customer Advances Account | حساب سُلف العملاء | `21` Current Liabilities | No |

All 8 are defined as: `value_type=integer`, `default_value=null`, `scope=company`, `display_group=production`, `is_visible=true`.

---

## Per-account detail (definition + consumption)

### 1. `production.wip_account_id` — Work-In-Progress
- **Def:** `ProductionSettingDefinitionSeeder.php:151-166`
- **Purpose:** Inventory WIP control account. **Debited** when material/labor/overhead is charged into a production order, **credited** as finished goods are received / order is closed.
- **Resolver:** `ProductionAccountResolver::resolveWip()` (`ProductionAccountResolver.php:67`), parent `11` Current Assets.
- **Consumed at (DR WIP):**
  - Material issue — `Listeners/PostMaterialIssueJournal.php:69` → DR WIP / CR Inventory (`production_material_issue`).
  - Labor confirmation — `Listeners/PostConfirmationJournals.php:53,79` → DR WIP / CR Labor Applied (`production_labor`).
  - Overhead confirmation — `Listeners/PostConfirmationJournals.php:53` → DR WIP / CR Overhead Applied (`production_overhead`).
  - Confirmation (in-Action variant) — `Actions/ConfirmOperation.php:552`.
  - Borrow (consignment) — `Actions/RecordBorrow.php:154`.
- **Consumed at (CR WIP):**
  - FG receipt — `Listeners/PostGoodsReceiptJournal.php:74,91` → DR FG / CR WIP (`production_fg_receipt`).
  - Toll FG receipt — `Listeners/PostGoodsReceiptJournal.php:167,180` → DR Toll Clearing / CR WIP.
  - Scrap — `Actions/PostScrapJournal.php:97` → DR Scrap / CR WIP.
  - Order close WIP settlement — `Actions/CloseProductionOrder.php:130` (DR or CR WIP to clear residual).

### 2. `production.fg_account_id` — Finished Goods
- **Def:** `ProductionSettingDefinitionSeeder.php:167-182`
- **Purpose:** Finished-goods inventory account, **debited** when produced quantity is capitalised out of WIP.
- **Resolver:** `resolveFg()` (`ProductionAccountResolver.php:81`), parent `11` Current Assets.
- **Consumed at:**
  - FG receipt — `Listeners/PostGoodsReceiptJournal.php:73,84` → DR FG / CR WIP.
  - Order close (non-toll residual) — `Actions/CloseProductionOrder.php:129` (DR FG to capitalise leftover WIP, or CR FG to return over-absorbed).

### 3. `production.scrap_account_id` — Production Scrap
- **Def:** `ProductionSettingDefinitionSeeder.php:183-198`
- **Purpose:** Expense account charged with the value of scrapped material / rejected output.
- **Resolver:** `resolveScrap()` (`ProductionAccountResolver.php:95`), parent `52` Operating Expenses.
- **Consumed at:** `Actions/PostScrapJournal.php:129` → DR Production Scrap / CR WIP (`production_scrap`). Header doc-comment at `PostScrapJournal.php:17-18`.

### 4. `production.labor_applied_account_id` — Labor Applied (absorption)
- **Def:** `ProductionSettingDefinitionSeeder.php:199-218`
- **Purpose:** Absorption/clearing account **credited** as labor cost is charged into WIP on operation confirmation. Carries a credit balance; cleared against actual labor at period end (a residual = over/under-absorbed labor variance). Sits under **Liabilities** by design (clearing convention) — see resolver header comment `ProductionAccountResolver.php:23-27`.
- **Resolver:** `resolveLaborApplied()` (`ProductionAccountResolver.php:110`), parent `21` Current Liabilities.
- **Consumed at:**
  - `Listeners/PostConfirmationJournals.php:61,87` → DR WIP / CR Labor Applied (`production_labor`).
  - `Actions/ConfirmOperation.php:560` (in-Action posting variant).

### 5. `production.overhead_applied_account_id` — Overhead Applied (absorption)
- **Def:** `ProductionSettingDefinitionSeeder.php:219-236`
- **Purpose:** Absorption/clearing account **credited** as manufacturing overhead (incl. machine cost) is absorbed into WIP on confirmation. Cleared against actual OH at month-end; the residual is the over/under-applied OH variance.
- **Resolver:** `resolveOverheadApplied()` (`ProductionAccountResolver.php:125`), parent `21` Current Liabilities.
- **Consumed at:**
  - `Listeners/PostConfirmationJournals.php:98` → DR WIP / CR Overhead Applied (`production_overhead`).
  - `Actions/ConfirmOperation.php:593` (in-Action variant).
  - Month-end OH settlement — `Actions/SettleAppliedOverhead.php:239` → clears Overhead Applied vs Cost Variance (`production_oh_settlement`, posting at `SettleAppliedOverhead.php:244-252`).
  - Utility-cost apportionment fallback — `Actions/ApportionUtilityCost.php:441` (used when a production center has no own overhead/expense account; comment at `ApportionUtilityCost.php:42`).

### 6. `production.cost_variance_account_id` — Production Cost Variance
- **Def:** `ProductionSettingDefinitionSeeder.php:237-256`
- **Purpose:** Expense account absorbing the **standard-vs-actual** delta on standard-costed FG receipts and the over/under-applied OH at settlement. DR when actual > std, CR when actual < std.
- **Resolver:** `resolveCostVariance()` (`ProductionAccountResolver.php:142`), parent `52` Operating Expenses (mirrors scrap).
- **Consumed at:**
  - Standard-cost FG receipt variance leg — `Listeners/PostGoodsReceiptJournal.php:102,105-113` (only posts when |variance| ≥ threshold).
  - Month-end OH settlement — `Actions/SettleAppliedOverhead.php:240` (under-applied → DR variance; over-applied → CR variance).
- **Note:** also read for a note string in `Actions/ComputeOrderVariances.php` (FOVV variance reporting), but the *account id* is only used in the two postings above.

### 7. `production.toll_clearing_account_id` — Toll Clearing
- **Def:** `ProductionSettingDefinitionSeeder.php:278-298`
- **Purpose:** Clearing account for **toll / customer-owned (consignment) manufacturing**. On a toll order's FG receipt, accumulated **conversion cost only** (labor + overhead — the customer's material was never valued into WIP) is parked here: DR Toll Clearing / CR WIP. Cleared later by the toll-fee Sales invoice. Sits under Current Assets as a receivable-style clearing account (resolver comment `ProductionAccountResolver.php:153-162`).
- **Resolver:** `resolveTollClearing()` (`ProductionAccountResolver.php:163`), parent `11` Current Assets.
- **Consumed at:**
  - Toll FG receipt — `Listeners/PostGoodsReceiptJournal.php:166,173` → DR Toll Clearing / CR WIP.
  - Toll order close (residual settles to clearing, not FG) — `Actions/CloseProductionOrder.php:128`.
  - Read for reporting in `Services/ProductionReportService.php:833`.

### 8. `production.customer_advance_account_id` — Customer Advances
- **Def:** `ProductionSettingDefinitionSeeder.php:299-317`
- **Purpose:** Liability account **credited** when a toll **down-payment** (customer advance) is recorded: DR Cash/Bank / CR Customer Advances. Cleared when the toll-fee invoice is raised. A current liability, NOT the customer's AR (resolver comment `ProductionAccountResolver.php:174-180`).
- **Resolver:** `resolveCustomerAdvance()` (`ProductionAccountResolver.php:181`), parent `21` Current Liabilities.
- **Consumed at:** `Actions/RecordTollDownPayment.php:76` → DR Cash / CR Customer Advances.

---

## How resolution works (so the /setup extension is wired correctly)
`ProductionAccountResolver::resolve()` (`ProductionAccountResolver.php:198-234`):
1. Read the setting via `SettingsService::get($key, $companyId)`.
2. If set **and** the account still exists for the company → use it (memoised per request).
3. Else `AutoAccountService::createChildAccount($companyId, $parentCode, $nameEn, $nameAr)` (a detail leaf under the parent header), then `SettingsService::set($key, $account->id, $companyId)` to persist it back.
4. A stale id (account deleted) falls through to re-creation.

**Implication for /setup:** to add these to the page, the FE should `GET` the current setting values (they may already be populated from prior postings) and `PUT`/update them via the same settings endpoint the existing 7 `accounting.*` keys use (`setup-wizard.component.ts:677-710`, batch update at `:866`). The account picker should restrict choices to **detail leaves** (never a header), matching the AR-header trap fix elsewhere in the system. Parents to filter under: WIP/FG/Toll → `11`; Scrap/Variance → `52`; Labor/OH Applied + Customer Advances → `21`.

---

## Related but NOT production default-account settings (do not add to the MFG accounts list)
- **Inventory credit leg of material issue:** `PostMaterialIssueJournal.php:117-154` resolves the *inventory* contra-account via the cross-module chain `sales.inventory_account_id` → `purchases.inventory_account_id` → `inventory.stock_account` (code) → auto-create under `11`. This is an **Inventory/Sales/Purchases** default account, not a Production one — cover it in those areas.
- **Non-account production settings** (in the same `production.*` group on `display_group=production`, but their value is NOT a GL account id — exclude from the Default-Accounts page):
  - `production.default_warehouse_id` (def `:40`), `production.under_process_warehouse_id` (def `:62`, consumed `Services/ProductionStagingResolver.php`) — warehouse ids, not accounts.
  - `production.allow_negative_wip` (`:78`), `production.backflush_shortage_policy` (`:95`), `production.costing_method` (`:113`), `production.labor_rate_source` (`:131`), `production.actual_overhead_source` (`:262`, consumed `SettleAppliedOverhead.php` + `ComputeOrderVariances.php:411`) — policy/enum flags.
  - `production.toll_margin_percent` (`:322`, consumed `CreateTollFeeInvoice.php:102`), `production.scrap_ncr_threshold_percent` (`:343`, consumed `RaiseNcrFromScrap.php:120`), `cvp.material_variable_percent` (`:368`, consumed `CvpService.php:436`), `pricing.default_overhead_percent` (`:392`, consumed `PricingService.php:241`) — numeric percents, not accounts.

---

## Open notes
- The resolver auto-names accounts in **English + Arabic** (e.g. "Work In Progress / إنتاج تحت التشغيل"). If `/setup` lets admins choose existing accounts instead, the auto-create path becomes a fallback only.
- No `Manufacturing` module exists — the module dir is **`Modules/Production`**. The settings namespace is `production.*` (single namespace, matches the permission prefix and sequence key — seeder header comment `ProductionSettingDefinitionSeeder.php:9-19`).
