Skip to content

Book 2 · Chapter 8 — Stock Operations

Scope. This chapter covers how the quantity-on-hand (QOH) of an inventory item at a store changes and how it is reconciled: stock takes & counts (freeze, count, variance), stock breaking / splitting (parent → child, auto-breaks, reverse splits, dispatches), stock processing (Sale/Short & Return/Excess reconciliation of count variances), stock & delivery loss (write-offs and employee charges), stock debtors / non-stock debtors (who owes for shortages), and the stock move report (the movement ledger).

It does not cover item CRUD / pricing (Chapter 7 — Maintain Items) nor GRN receiving (Chapter 9 — Purchasing & GRN). Those modules also write to the same ledger; this chapter explains how reconciliation movements are produced.


1. Purpose (plain language)

A distributor's warehouse never perfectly matches the numbers in the system. Boxes get broken down into pieces, deliveries get damaged, staff miscount, items go missing. Stock Operations is the toolkit Bizwiz gives a branch to keep the "on paper" stock equal to the "on the shelf" stock, and to assign blame (and money) when they differ.

There are five everyday jobs in this chapter:

  1. Stock take / count — "Freeze what the system thinks we have, send people to physically count the shelves, then compare." The freeze captures a snapshot of QOH; counters key in what they actually see; the system produces a variance (counted − frozen).

  2. Stock breaking (splitting) — "We have cartons but customers want single bottles." A mother item (e.g. a carton) is broken into a child item (e.g. loose bottles). This reduces the mother's QOH and increases the child's QOH. It can be done manually, requested from the shop floor, or triggered automatically when a sale needs child stock that isn't there. Reverse splits undo a break (child back to mother).

  3. Stock processing — Once a count reveals a variance, someone must "process" it. A shortage (Sale/Short) is booked as if the missing stock was sold to the responsible staff member (they now owe money). An excess (Return/Excess) is booked as a return (stock added back, staff credited).

  4. Stock loss & delivery loss — Deliberate write-offs. Stock loss removes damaged/lost store stock and optionally charges an employee. Delivery loss handles goods damaged in transit to a customer — it credits the customer's invoice balance and charges staff, but does not touch store QOH (the stock already left).

  5. Stock debtors — The ledger of people who owe stock/money because of the above. Stock debtors are registered accountable staff (store-keepers, salesmen); non-stock debtors are ad-hoc users who picked up a variance charge without a master record. Debt can be split between people.

The Stock Move Report ties it all together: for any item/location it shows opening balance, every inflow (purchases, transfers, breaks-in, adjustments) and outflow (sales, transfers, breaks-out, losses), and the closing balance.

The single unifying fact for this whole chapter:

QOH is not stored as a column. It is the running sum of wa_stock_moves.qauntity for an item at a location. Every operation in this chapter — a break, a count adjustment, a loss — reconciles by writing one or more rows into wa_stock_moves. Each row also snapshots the resulting balance in new_qoh.


The rest of this chapter is the technical layer.


2. Users & roles (+ permission strings)

All screens live under the Inventory → Stock Take and Inventory → Stocks Break sidebar groups (resources/views/admin/includes/sidebar_includes/inventory.blade.php). Access is gated either by the legacy $my_permissions['<model>___<action>'] map or the newer can('<action>', '<model>') helper. The super-admin role (config('app.allowed_role')) sees everything.

Stock takes & counts

Screen Permission Route name
Create Stock Take Sheet stock-take___view admin.stock-takes.create-stock-take-sheet
Assign Stock Count Users stock-take-user-assignment___view admin.stock-counts-users-assingment
Enter Stock Counts stock-counts___view admin.stock-counts
Live Stock Count stock-counts___add admin.live-stock-count
Detailed Variance Report stock-count-variance___detailed-view admin.stock-count-variance.index
Summary Variance Report stock-count-variance___summary-view admin.stock-count-variance.summary
Blocked Users stock-count-blocked-users___view admin.stock-count-blocked-users.index
Exemption Schedules stock-count-blocked-users-exemption-schedules___view admin.stock-count-blocked-users.exemption-schedules

Stock breaking

Screen Permission Route name
Stock Breaking stock-breaking___view / ___add / ___edit stock-breaking.index (resource)
Split Requests display-split-requests___view / ___approve / ___reject stock-breaking.split-requests
Auto Breaks stock-auto-breaks___view stock-auto-breaks.index
Reverse Splits reverse-splits___view / ___add / ___approve / ___reject reverse-splitting.index (resource)
Pending / Dispatched / Completed Dispatches stock-auto-breaks___dispatch stock-auto-breaks.dispatch.*
Summary stock-breaking___summary stock-breaking.summary

Additional break permissions: stock-breaking___split-on-behalf (break for another branch), stock-breaking___create-dispatch, stock-auto-breaks___view-all / reverse-splits___view-all (bypass the "only my bin" restriction).

Stock processing, debtors, losses

Screen Permission Route name
Sale (Short) stock-processing-sales___view (parent stock-processing___view) stock-processing.sales
Return (Excess) stock-processing-return___view stock-processing.return
Uncompleted Entries stock-uncompleted-sales___view stock-uncompleted-sales.index
Stock Debtors stock-debtors___view / ___add / ___split stock-debtors.index
Non-Stock Debtors stock-non-debtors___view stock-non-debtors.index
Stock Loss (Store) can('view'/'create'/'approve'/'reject', 'stock-loss') inventory.stock-loss.*
Delivery Loss (Customer) can('view'/'create'/'approve'/'reject', 'delivery-loss') inventory.delivery-loss.*
Stock Move Report stock-move-report___view / ___export stock-move-report.index

Permission definitions live in app/Permissions/Inventory.php.

Typical operators: warehouse/store keepers key counts and initiate breaks; a stock-count supervisor freezes sheets and assigns counters; branch managers/accountants process variances, approve losses, and manage the debtors ledger. Role 152 (store keeper) is special-cased in several controllers to scope views to the user's own store (e.g. StockTakesController@index).


3. Processes (trigger → states → routes → outcome)

3.1 Stock take & count (freeze → count → variance → process)

flowchart TD
    A["Create Stock Take Sheet<br/>StockTakesController@freezeTable"] -->|snapshot QOH| B[(wa_stock_check_freezes<br/>+ wa_stock_check_freeze_items)]
    B --> C[Assign Count Users<br/>StockTakeUserAssignmentController]
    C --> D["Enter Stock Counts<br/>StockCountsController@updateStockCounts"]
    D --> E[(wa_stock_counts)]
    E --> F[Variance = counted - frozen QOH<br/>WaStockCountVariation]
    F --> G{Variance sign}
    G -->|negative shortage| H[Sale / Short processing]
    G -->|positive excess| I[Return / Excess processing]
    H --> J["(wa_stock_moves: -qty)<br/>+ stock_debtor_trans"]
    I --> K["(wa_stock_moves: +qty)<br/>+ stock_debtor_trans credit"]

Step 1 — Freeze (create sheet). From Create Stock Take Sheet the user picks a store, one or more inventory categories, and a UOM/count type. StockTakesController@addStockCheckFile (:149-386) creates a WaStockCheckFreeze header (wa_stock_check_freezes: store, user, category-id list, UOM, count_type, expires_at) and one WaStockCheckFreezeItem row per item (wa_stock_check_freeze_items), each capturing the quantity_on_hand at freeze time — the immutable "system says" snapshot. The freeze does not stop sales; it records a baseline. Two settings adjust the frozen figure before it is stored: - EXCLUDE_OVERFLOW_STOCKS_FROM_STOCK_COUNT_SHEET — subtracts overflow-store moves (wa_stock_moves_C, wa_stock_moves_supreme, wa_overflow_stock_moves) so the sheet only reflects main-store stock (:160-208). - DEDUCT_UNDISPATCHED_STOCKS_FROM_STOCK_COUNT_SHEET — deducts route/invoice stock that is staged but not yet physically dispatched (from salesman_shift_store_dispatch_items, wa_internal_requisition_items), storing the breakdown in wa_stock_check_freeze_undispatched_items (:214-295).

(freezeTable() is a separate maintenance action that truncates the store-C freeze tables.)

Step 2 — Assign counters. StockTakeUserAssignmentController (models StockTakeUserAssignment, StockTakeUserAssignmentAssignee) allocates specific items/bins to specific users so counting can be divided up and audited. Assignments can be one-time or is_persistent (recur daily until end_date); supports CSV/batch upload of item allocations into display_bin_user_item_allocations.

Step 3 — Enter counts. Enter Stock Counts (StockCountsController@updateStockCounts, :92-250) or Live Stock Count (LiveStockCountController, which freezes-and-shows a single item on demand for spot counts, count_type='live_count') persists the physically counted quantity into wa_stock_counts (WaStockCount) and immediately writes a variance row.

Step 4 — Variance. Variance is stored in WaStockCountVariation (wa_stock_count_variation) with quantity_recorded (counted), current_qoh (frozen snapshot), variation, count_type (daily_freeze/live_count), and is_processed. The formula (StockCountsController.php:230-234) is:

variance = (current_qoh < 0) ? quantity_recorded + current_qoh
                             : quantity_recorded - current_qoh
So counted 95 vs frozen 100 → -5 (shortage); counted 105 → +5 (excess). Reported two ways: Detailed (StockCountVarianceReportController@index, line-level, attach a reference note via updateReference + referenceHistory, plus undispatchedBreakdown that itemises route/POS/ invoice stock counted-but-undispatched) and Summary (@summary).

Step 5 — Process / apply. There are two distinct "apply" paths: - Direct QOH adjustment — StockCountsController@compareCountsVsStockCheckProcess (:396-547) computes adjustment = counted − system_qoh, and for each non-zero adjustment writes a wa_stock_moves row (stock_adjustment_id = 2, signed qauntity, new_qoh = prior sum + adjustment), two wa_gl_trans rows (DR/CR against usage/stock/price-variance accounts, valued at standard_cost × adjustment), and a WaStockCountDeviation audit row; it then clears the temporary wa_stock_counts / wa_stock_count_process rows. This is the count subsystem directly reconciling QOH + posting GL. - Debtor processing — alternatively the variance flows to Stock Processing (§3.3), where a negative variance becomes a Sale/Short (staff charged) and a positive one a Return/Excess; processing marks WaStockCountVariation.is_processed = 1.

Blocked users / exemptions. StockCountBlockedUsersController blocks counters with incomplete counts (users.is_blocked), supports unblockAll/unblockSelected, and manages block_users_exemption_schedules that excuse specified store-keepers (role 152) for the next day.

⚠️ Opening-balances & store-C/supreme/overflow variants are separate stacks. OpeningBalancesStockTakeController, StoreCStockTakeController, SupremeStoreStockTakeController, OverflowStockTakeController mirror this flow with their own opening_balances_*, store_c_stock_*, supreme_store_stock_*, overflow_stock_* tables. They are gated by store-type settings (e.g. ACTIVATE_OVERFLOW_STORE) and are out of core scope here — flagged in §7.

3.2 Stock breaking (parent → child)

"Breaking" converts a mother/parent item into a child item using a conversion factor (child units per parent unit; e.g. 1 carton = 12 bottles). Every break writes two wa_stock_moves rows: parent −source_qty and child +destination_qty.

There are four entry points, all landing on the same ledger:

stateDiagram-v2
    [*] --> PENDING: manual save (request_type=save)
    PENDING --> PROCESSED: manual store / update (creates stock moves)
    PROCESSED --> DISPATCHED: createDispatch
    DISPATCHED --> COMPLETED: receive

    [*] --> AB_pending: AutoBreakingService (sale needs child)
    AB_pending --> AB_processed: initiateDispatch
    AB_processed --> AB_dispatched: processDispatch
    AB_dispatched --> AB_received: receive

(a) Manual break — stockBreakingController (resource stock-breaking). store() validates source/destination, creates a WaStockBreaking header + WaStockBreakingItem lines and, unless merely saved as a draft, immediately writes the two ledger moves (stockBreakingController.php:898-938). prepopulateItems() / getDestinationSalesQty() are suggestion engines that recommend what to break based on child minimum (minimum-quantity-of-child-item) and recent sales velocity (average-sales-days-to-compute-stock-break, default 2 days).

(b) Shop-floor split request — display-bin users request a break (mobile or web requestSplitsWeb). Requests queue as PosStockBreakRequest (status=pending). A manager reviews them under Split Requests and approveSplitRequests() (MobileInventoryManagementController.php:285-321) writes the two moves and one grouped WaStockBreaking.

(c) Auto break — AutoBreakingService::attemptAutoBreak() fires during sales-order processing when the ordered child QOH is insufficient but a configured mother item has stock. It creates a WaStockBreaking (PROCESSED), writes parent −qty / child +qty moves (AutoBreakingService.php:376-450), and logs a RouteAutoBreak audit row. These then flow through the dispatch lifecycle in RouteAutoBreakController (pending → dispatched → received), which coordinates the physical movement between mother-bin and child-bin via StockBreakDispatch / StockBreakDispatchItem but does not re-touch QOH (the ledger was already written at break time).

(d) Reverse split — ReverseSplitsController undoes a break. store() creates a ReverseSplit (status=pending, no QOH change). On approve() (ReverseSplitsController.php:328-358) it writes the inverse moves: mother +expected_qty, child −requested_qty, with a REVERSE_STOCKBREAKING document number. reject() sets status=rejected.

Summary (RouteAutoBreakController@summary) aggregates both manual (WaStockBreakingItem) and auto (RouteAutoBreak) breaks by date/mother item for reporting.

3.3 Stock processing (Sale/Short & Return/Excess)

StockAdjustmentController turns an unprocessed count variance into a booked movement plus a debtor charge.

Sale (Short) — variance < 0 (physical < system): stock_processing_sales_store generates an SAS-##### document (series STOCK_ADJUSTMENT_SALES), creates a StockDebtorTran header + StockDebtorTranItem lines, and for each item writes a negative wa_stock_moves row (StockAdjustmentController.php:316-367). If current QOH ≥ needed qty the whole shortage is processed; if QOH is partial it books what's available and leaves quantity_pending > 0 (is_processed = 0). GL: debit Debtors Control, credit Sales Revenue + VAT. The debtor now owes the value. An ESD/eTIMS tax invoice is auto-signed (signInvoice()).

Return (Excess) — variance > 0 (physical > system): stock_processing_return_store generates SAR-##### (series STOCK_ADJUSTMENT_RETURN), always writes a positive wa_stock_moves row (StockAdjustmentController.php:850-871), and creates negative-value debtor lines (a credit). If the UOM is a display bin, the excess is attributed to the allocated non-debtor user via display_bin_user_item_allocations. GL is the reverse of a sale.

Uncompleted Entries — StockUncompletedProcessingController@process re-attempts the partially-processed SAS lines (quantity_pending > 0) once stock is replenished, writing the remaining negative moves (:172-221).

stateDiagram-v2
    [*] --> Unprocessed: variance created (is_processed=0)
    Unprocessed --> Processed: full qty available (is_processed=1)
    Unprocessed --> Partial: partial qty (quantity_pending>0)
    Partial --> Processed: Uncompleted process re-run

3.4 Stock loss (store) & delivery loss (customer)

Both are create → pending → approve/reject workflows with optional employee charges and (setting-gated) signed acknowledgement documents.

Stock Loss (StockLossController): records lost/damaged store stock (SL-######). On approve() it writes a negative wa_stock_moves row per item (StockLossController.php:308-331, −qty_lost) and creates an EmployeePenalty (polymorphic → StockLoss) for each charged employee. reject() makes no QOH change.

Delivery Loss (DeliveryLossController): loss in transit to a customer, tied to a sales invoice (WaInternalRequisition), document DL-######. On approve() it creates a negative WaDebtorTran (credits the customer's invoice balance, DeliveryLossController.php:328-366), creates employee penalties, and posts GL via DeliveryLossGlPostingService. It does NOT write wa_stock_moves — the stock already left the store when it was invoiced, so only the customer balance and staff liability move.

3.5 Stock debtors & non-stock debtors

StockDebtorsController maintains the ledger of who owes for shortages. - Stock debtors = registered accountable staff (StockDebtor master + StockDebtorTran / StockDebtorTranItem). Balance = SUM(stock_debtor_trans.total). - Non-stock debtors = users with variance charges but no master record (tracked via stock_debtor_trans.stock_non_debtor_id). - Splits: split, split_non_debtors, nonDebtor_Debtor_split, nonDebtor_nonDebtor_split distribute a debt across multiple people using an SDS-##### (STOCK_DEBT_SPLIT) document — a negative tran on the source, positive trans on recipients. move_non_stock_debtors demotes a registered debtor to a non-debtor (keeps the liability, removes the master row).

These screens move money/liability, not QOH — the QOH already moved during stock processing.

3.6 Stock Move Report

StockMoveReportController reads wa_stock_moves and classifies each movement by its foreign keys into inflows/outflows: purchases_in (has wa_purchase_order_id), transfers_in/out (has wa_inventory_location_transfer_id), sales_out (has wa_internal_requisition_id), and others_in/out (breaks, losses, adjustments — no PO/transfer/requisition link). For each item/location it computes opening (sum of moves before the from-date) + inflows − outflows = closing (StockMoveReportController.php:61-299), with optional UOM conversion when INVENTORY_SETUP = 'UOM BASED'. Exportable to Excel. Gated in the sidebar by the identify-sales-orders-from-normal-orders setting.


4. Tables touched & key data

The ledger (central): - wa_stock_moves (WaStockMove) — the QOH ledger. Key columns: wa_inventory_item_id, wa_location_and_store_id, stock_id_code, qauntity (signed movement, note the mis-spelling), new_qoh (balance snapshot after this move), document_no, and the source FKs (wa_purchase_order_id, wa_internal_requisition_id, wa_inventory_location_transfer_id, stock_adjustment_id, wa_pos_cash_sales_id) used to categorise movements. QOH(item, store) = SUM(qauntity) over matching rows.

Stock take / count: - wa_stock_check_freezes / wa_stock_check_freeze_items (WaStockCheckFreeze / WaStockCheckFreezeItem) — freeze header + per-item frozen quantity_on_hand snapshot (plus undispatched_quantity when that setting is on). - wa_stock_check_freeze_undispatched_items — audit breakdown of undispatched qty deducted from the freeze (source_type = Route/Invoice/POS). - wa_stock_counts (WaStockCount) — physical counts keyed by users (temporary; cleared on process). - wa_stock_count_variation (WaStockCountVariation) — quantity_recorded, current_qoh, variation, count_type, is_processed. - wa_stock_count_deviations (WaStockCountDeviation) — post-process audit trail of applied adjustments (batch_date, before/after qty). - wa_stock_count_process (WaStockCountProcess) — count processing status (selected_type). - wa_gl_trans (WaGlTran) — GL journal rows posted when counts are directly applied. - stock_take_user_assignments / stock_take_user_assignment_assignees — counter allocation; block_users_exemption_schedules / _users — count-block exemptions.

Stock breaking: - wa_stock_breaking / wa_stock_breaking_items (WaStockBreaking / WaStockBreakingItem) — manual/auto break header + lines (source_item_id, source_qty, destination_item_id, destination_qty, conversion_factor, status, dispatched). - route_auto_breaks (RouteAutoBreak) — auto-break audit trail. - reverse_splits (ReverseSplit) — reverse-split requests. - pos_stock_break_requests (PosStockBreakRequest) — shop-floor split requests. - stock_break_dispatches / stock_break_dispatch_items (StockBreakDispatch / StockBreakDispatchItem) — physical mother-bin → child-bin dispatch lifecycle.

Processing / debtors / losses: - stock_debtors / stock_debtor_trans / stock_debtor_tran_items (StockDebtor / StockDebtorTran / StockDebtorTranItem). - stock_losses / stock_loss_items / stock_loss_employee_charges (StockLoss / StockLossItem / StockLossEmployeeCharge). - delivery_losses / delivery_loss_items / delivery_loss_employee_charges (DeliveryLoss / DeliveryLossItem / DeliveryLossEmployeeCharge). - employee_penalties (EmployeePenalty, polymorphic to StockLoss/DeliveryLoss). - wa_debtor_trans (WaDebtorTran) — customer balance adjustment for delivery loss.


5. Interactions with other modules

QOH is shared. The wa_stock_moves ledger written by this chapter is the same QOH that: - Sales / POS reads to check availability and decrements on a sale (wa_internal_requisition_id / wa_pos_cash_sales_id moves). - GRN / Purchasing (Ch 9) increments on receiving (wa_purchase_order_id moves). - Inter-branch transfers move between stores (wa_inventory_location_transfer_id moves).

Because QOH is a live sum, operations in this chapter have immediate cross-module effects:

Operation Effect on QOH Who sees it
Stock take freeze none (snapshot only) reconciliation only
Count → direct apply (compareCountsVsStockCheckProcess) ± adjustment (counted − system) Sales sees corrected QOH; GL posted
Count → Sale/Short processing − child qty Sales sees less available; debtor charged
Count → Return/Excess processing + item qty Sales sees more available
Manual/auto/request break − mother, + child Sales can now sell child units
Reverse split + mother, − child mother available again
Stock loss approve − lost qty Sales sees less; employee penalty
Delivery loss approve no QOH change; customer credited, staff charged AR / debtors

Auto-break ↔ Sales. The tightest coupling: AutoBreakingService is invoked inside sales order processing so a child-item sale can succeed by transparently breaking a mother item — the sale and the break both hit the ledger in the same flow.

Stock processing ↔ Finance/GL & Tax. Sale/Short and Return/Excess post GL journals (Debtors Control / Sales Revenue / VAT) and auto-sign an ESD/eTIMS tax invoice. Delivery loss posts GL via DeliveryLossGlPostingService. Losses create EmployeePenalty rows consumed by HR/Payroll for deduction.

Display bins ↔ POS. Split requests and excess attribution rely on display_bin_user_item_allocations linking display-bin UOMs to specific POS users.


6. Alternatives & variants (manual vs automated, flavor differences)

  • Breaking is manual, requested, or automatic. Manual (stockBreakingController), shop-floor-requested (PosStockBreakRequest → manager approval), or automatic during a sale (AutoBreakingService). All converge on identical parent−/child+ ledger moves. Reverse splits provide the undo path.
  • Break drafts. Manual breaks can be saved as a PENDING draft (request_type=save, no ledger write) and later processed; auto/approved breaks are created directly as PROCESSED.
  • Two ways to settle a count. A variance can be directly applied to QOH+GL by the count supervisor (compareCountsVsStockCheckProcess), or routed through Stock Processing to charge a debtor. Confirm per deployment which path a given branch uses (they are not mutually exclusive in code).
  • Freeze adjustments are setting-gated. EXCLUDE_OVERFLOW_STOCKS_FROM_STOCK_COUNT_SHEET and DEDUCT_UNDISPATCHED_STOCKS_FROM_STOCK_COUNT_SHEET change what "system QOH" means on the sheet; SHOW_SYSTEM_QOH_ON_PRINTED_STOCK_TAKE_SHEET toggles whether counters see the system figure on the printed sheet; activate-subbins groups the sheet by subbin.
  • Signed-acknowledgement gate. ENFORCE_SIGNED_ACKNOWLEDGEMENT_FOR_LOSS_CHARGES toggles whether an employee-charge document upload is required vs optional on stock/delivery loss.
  • UOM-based inventory. INVENTORY_SETUP = 'UOM BASED' enables multi-UOM conversion in the Stock Move Report (base/second/third UOM) and drives the count-type/UOM selection on freezes.
  • Sales-order feature flag. The Stock Move Report menu entry is gated by identify-sales-orders-from-normal-orders.
  • Store-type stacks. Store-C, Supreme Store, Overflow Store, and Opening-Balances each have a parallel stock-take controller + tables, activated per flavor (e.g. ACTIVATE_OVERFLOW_STORE). Core "Stock Take" is the default StockTakesController stack.
  • Break suggestions are tunable per branch via minimum-quantity-of-child-item and average-sales-days-to-compute-stock-break settings.

7. Open questions to confirm

CODE-PROVEN (verified in this pass): - QOH is a running sum of wa_stock_moves.qauntity; new_qoh snapshots the balance. (migration 2023_09_08_134414_create_wa_stock_moves_table.php; model WaStockMove.) - Freeze snapshots per-item quantity_on_hand into wa_stock_check_freeze_items. (migration 2023_09_08_134414_create_wa_stock_check_freeze_items_table.php.) - Every break/reverse/loss/processing operation writes signed ledger rows at the cited lines. - Delivery loss does not write wa_stock_moves — only wa_debtor_trans + penalties. - Variance formula and the direct count-apply path (wa_stock_moves + wa_gl_trans + WaStockCountDeviation) verified at StockCountsController.php:230-234 and :396-547. - Freeze QOH is adjusted by overflow/undispatched settings before snapshot (StockTakesController.php:160-295).

INFERENCES (need a maintainer to confirm): - The exact rule mapping a negative variance → Sale/Short and positive → Return/Excess is derived from the store methods' filters; confirm whether a supervisor can override the sign/route, and whether the direct-apply path and the debtor-processing path can both run on the same variance. - Whether the RouteAutoBreak dispatch lifecycle (pending→dispatched→received) is purely a physical-movement audit with no second QOH mutation (strongly implied, since the ledger is written at break time) — confirm no receive() re-posts moves. - How stock_id_code vs wa_inventory_item_id are used together in the QOH SUM (batch/lot granularity?) — needs a maintainer to confirm the exact grouping key. - Store-C / Supreme / Overflow / Opening-Balances variants were not traced in depth this pass; confirm they use their own *_stock_moves equivalent or share wa_stock_moves. - deviationReport / WaStockCountDeviation and compareCountsVsStockCheck relationships were observed by route name but not line-traced.


8. Source references

Navigation & routes - resources/views/admin/includes/sidebar_includes/inventory.blade.php (Stock Take menu :866-1038; Stocks Break menu :374-445; Debtors/Processing/Loss :939-1035). - routes/web.php — stock breaking :1585-1595; reverse splits :1591-1593; stock-takes :3855-3861; live count :3864-3871; stock counts + variance :3873-3884; user assignment :3887-3910; blocked users :3893-3899; debtors :3947-3966; processing :3968-3994; auto-breaks :5652-5663; break summary/split-requests :5664-5670; stock-move-report :5461-5463. - routes/modules/inventory.php — stock loss :71-84; delivery loss :87-98.

Controllers - app/Http/Controllers/Admin/StockTakesController.php — freeze/sheet; snapshot :149-386, overflow exclusion :160-208, undispatched deduction :214-295. - app/Http/Controllers/Admin/StockTakeUserAssignmentController.php — counter allocation. - app/Http/Controllers/Admin/StockCountsController.php — enter counts :92-250, variance formula :230-234, direct QOH+GL apply :396-547, deviation report :370-384. - app/Http/Controllers/Admin/LiveStockCountController.php — spot counts (live_count). - app/Http/Controllers/Admin/StockCountVarianceReportController.php — variance reports, undispatched breakdown :207-230. - app/Http/Controllers/Admin/StockCountBlockedUsersController.php — blocked users/exemptions. - app/Http/Controllers/Admin/stockBreakingController.php — manual break; QOH moves :898-938, update :1116-1156, dispatch :1187-1304. - app/Http/Controllers/Admin/RouteAutoBreakController.php — auto-break dispatch lifecycle, summary :376-487. - app/Http/Controllers/Admin/ReverseSplitsController.php — reverse split; QOH moves :328-358. - app/Http/Controllers/Admin/MobileInventoryManagementController.php — split requests; approve QOH moves :285-321. - app/Services/AutoBreakingService.php — auto break; QOH moves :376-450. - app/Http/Controllers/Admin/StockAdjustmentController.php — Sale/Short :316-367, Return/Excess :850-871, ESD signing :1094-1169. - app/Http/Controllers/Admin/StockUncompletedProcessingController.php — uncompleted :172-221. - app/Http/Controllers/Admin/StockDebtorsController.php — debtors & splits. - app/Http/Controllers/Admin/StockLossController.php — store loss; approve QOH :308-331. - app/Http/Controllers/Admin/DeliveryLossController.php — delivery loss; approve :328-366. - app/Http/Controllers/Admin/StockMoveReportController.php — move report :61-299.

Models (App\Model\* and App\Models\*) - Ledger: WaStockMove. - Freeze/count: WaStockCheckFreeze, WaStockCheckFreezeItem, WaStockCount, WaStockCountVariation, WaStockCountDeviation, WaStockCountProcess, StockTakeUserAssignment, StockTakeUserAssignmentAssignee. - Breaking: WaStockBreaking, WaStockBreakingItem, RouteAutoBreak, ReverseSplit, PosStockBreakRequest, StockBreakDispatch, StockBreakDispatchItem. - Debtors/loss: StockDebtor, StockDebtorTran, StockDebtorTranItem, StockLoss, StockLossItem, StockLossEmployeeCharge, DeliveryLoss, DeliveryLossItem, DeliveryLossEmployeeCharge, EmployeePenalty, WaDebtorTran.

Migrations - database/migrations/2023_09_08_134414_create_wa_stock_moves_table.php. - database/migrations/2023_09_08_134414_create_wa_stock_check_freezes_table.php. - database/migrations/2023_09_08_134414_create_wa_stock_check_freeze_items_table.php. - database/migrations/2024_05_14_075547_create_wa_stock__count_variation_table.php. - database/migrations/2023_09_08_134414_create_wa_stock_counts_table.php. - database/migrations/2023_09_08_134414_create_wa_stock_count_deviations_table.php. - database/migrations/2025_11_12_100335_add_count_type_to_stock_tables.php (adds count_type). - database/migrations/2026_07_14_100000_create_wa_stock_check_freeze_undispatched_items_table.php.

Key settings (slugs / flags) - Breaking: minimum-quantity-of-child-item, average-sales-days-to-compute-stock-break. - Freeze/count: EXCLUDE_OVERFLOW_STOCKS_FROM_STOCK_COUNT_SHEET, DEDUCT_UNDISPATCHED_STOCKS_FROM_STOCK_COUNT_SHEET, SHOW_SYSTEM_QOH_ON_PRINTED_STOCK_TAKE_SHEET, activate-subbins, ACTIVATE_OVERFLOW_STORE. - Loss: ENFORCE_SIGNED_ACKNOWLEDGEMENT_FOR_LOSS_CHARGES. - Reports: INVENTORY_SETUP (UOM BASED), identify-sales-orders-from-normal-orders.

Permissions - app/Permissions/Inventory.php.