Wiki 🔍 Search
QIIUB · Module completeness

Adjustments

27 scored features 9 dependencies + N/A area: Inventory & Supply Chain

measured at 56d2d327

63%
Overall
T1100%
T236%
T39%

Created: 2026-07-27 | Last Updated: 2026-07-27

Fifth filled instance of module-scorecard-template.md (after PO, Receivings, Transfers, Distribution) — the last member of the inventory-movement family. Read-only analysis; recommendations only. Evidence is file:line / endpoint against D:\BCPOSGit\qiiub on branch main at commit 56d2d327. Gathering source-of-record: artifact-adjustments-gathering-{repo,rmhrms,wids365,market}.md. Scored with all four source families (RMS/RMH + WIDS365 + modern market + QIIUB-original).


0. Document control

Field Value
Module name Adjustments (Inventory Adjustments)
File adjustments-scorecard.md (docs/modules/adjustments-scorecard.md)
Author / session Claude (Opus) — module #5
Created 2026-07-27
Last-Updated 2026-07-27
Repo commit (SHA) analyzed 56d2d327
Governing ADRs 0081 (Inventory Hub IA), 0082 (PublicId/TypeID), 0083 (posted-document), 0023 (three-tier history), 0020 (LocationProduct not StockLevel), 0004 (bigint PK), 0062 (user attribution), 0067 (tax-holiday resolver) — evidence only; this scorecard creates none
Governing design docs docs/design/inventory-supply-chain.md §4.5 / §5.2
Status of this analysis Adversarially-verified — Fable pass moved 76→63 (findings + resolutions in artifact-adjustments-fable-review.md); live-confirmed against the running app 2026-07-28 (§5c)

Last-Updated = the measurement date, pinned to commit: — bumped only on a re-score (.claude/rules/docs.md carve-out).


1. Module identity


2. Dependency map

Module Direction What crosses the boundary Scoring treatment
Reason Codes (cross-cutting reference data) shared-infra The ReasonCode catalog Adjustments requires on every header dependency — out of scope (ADJ-D01)
Stock Counts upstream Count finalize auto-creates a Completed adjustment from variance (reason CYCLE-COUNT) dependency (ADJ-D02)
Transfers upstream Damage-on-receive auto-creates a Completed adjustment (reason ADJ-XFR-DAMAGE) dependency (ADJ-D03)
Receivings shared pattern Receipt quantity/cost correction is a Receivings concern, not an adjustment dependency (ADJ-D04)
Inventory core shared-infra InventoryMovement ledger + LocationProduct.QuantityOnHand that Complete writes dependency (ADJ-D05)
Reports downstream Shrinkage / variance-by-reason reporting dependency (ADJ-D06)
Document sequencing shared-infra IDocumentSequenceService mints ADJ-###### dependency (ADJ-D07); the use (documents carry a number) is scored ADJ-F007

Boundary statement. Adjustments owns the InventoryAdjustment + InventoryAdjustmentLine tables, all 10 endpoints under Api/Features/Adjustments/, the Draft → Completed | Cancelled state machine, and the manual act of posting a reason-coded quantity change. It does not own the ReasonCode catalog, the InventoryMovement/LocationProduct tables it writes, or the two neighbor flows that create adjustment documents automatically (Stock Counts, Transfers). Those neighbors physically construct an InventoryAdjustment, but the semantic capability (cycle-count variance; transfer damage) belongs to them — single-owner rule.

Boundary-leak checklist.

Single-owner rule. Verified: none of the 27 scored features here is also scored in PO / Receivings / Transfers / Distribution / Stock Counts. The three auto-adjustment writers are Dependency rows, not scored.


3. Functional taxonomy

Status legend: Implemented / Partial / Missing / Dependency (excluded). Source: RMS / RMH / WIDS365 / market / QIIUB-original.

Comparison map, not a backlog. Universe = RMS/RMH + WIDS365 (a BCPOS production POS with a first-class Adjustment document) + modern inventory tooling (Square/Lightspeed/Shopify+Stocky/Clover/NetSuite/Cin7/Odoo) + QIIUB-original. A Missing means "that world has it and QIIUB doesn't (yet)," not a commitment.

About the reference systems. RMS (Microsoft Dynamics Retail Management System) is the older base; RMH (Retail Management Hero) is its current, actively-developed successor — built on the RMS database to keep upgrades smooth, and extending it with additional tables plus visual and integration extensions. RMH is one of the products BCPOS resells. (RMS's Headquarters / HQ is called Central in RMH.) They are used here as a completeness yardstick, not a competitive ranking: where QIIUB does something differently, that reflects its cloud / single-database architecture, not a judgment that RMS/RMH is inferior. QIIUB is a newer evolution alongside them.

Market shape (from the 4-source scan). Inventory adjustments split cleanly into two tiers: a table-stakes POS tier (manual single + reason, lifecycle, history, list) that every system has, and an ERP tier (value/cost revaluation, GL posting, back-date, reversal, approval) that pure POS systems omit. QIIUB has the full table-stakes tier and none of the ERP tier — which is exactly the T1-complete / T3-sparse shape below. Notably, adjustment approval workflow is rare even in ERP (NetSuite has no native approval), so building it would meet-or-beat the market.

T1 — Core (module unusable without) — weight ×3

ID Name Description Source Status Evidence Notes
ADJ-F001 Create adjustment (Draft) Draft header (one location + reason) + optional signed lines RMS+RMH+WIDS365+market Implemented CreateAdjustment/CreateAdjustmentEndpoint.cs:103 Resolves Location/ReasonCode/variant PublicIds; snapshots cost/price; mints ADJ-######
ADJ-F002 Signed quantity change per line Per-line QuantityChange (+ increase / − decrease) RMS+RMH+WIDS365+market Implemented InventoryAdjustmentLine.cs:16; CreateAdjustmentEndpoint.cs:65-67 (NotEqual 0) Signed delta, not a target count — same model as WIDS365
ADJ-F003 Reason-coded (required) Every adjustment carries a reason from the catalog RMS+RMH+WIDS365+market Implemented InventoryAdjustment.cs:17 (non-null); CreateAdjustmentEndpoint.cs:118-125 Required by default — stronger than RMS/RMH (there it is config-driven "recommended") and matches WIDS365 (header-required)
ADJ-F004 Complete → post to inventory Complete writes InventoryMovement + upserts LocationProduct.QuantityOnHand, one transaction RMS+RMH+WIDS365+market Implemented CompleteAdjustmentEndpoint.cs:77,146-205,208-209 The core purpose. Atomic flip + per-line movement + QoH upsert + concurrency retry (#964)
ADJ-F005 Line management Add / update / remove / atomic bulk-remove lines on a Draft RMS+RMH+WIDS365+market Implemented AddLine :60, UpdateLine :62, RemoveLine :30, RemoveLines batch #799 ProductVariant immutable on a line (remove+re-add); LineNumber auto max+1
ADJ-F006 Status lifecycle Draft → Completed | Cancelled; only Draft is mutable RMS+RMH+WIDS365+market Implemented AdjustmentStatus.cs; 409 guards in 5 endpoints; atomic flips Both terminal states are atomic WHERE Status=Draft flips (no lost-update). Maps to WIDS365 Open→Closed / RMS Commit
ADJ-F007 Document numbering Human ADJ-###### per merchant RMS+RMH+WIDS365 Implemented CreateAdjustmentEndpoint.cs:156 via IDocumentSequenceService Unique (MerchantId, DocumentNumber). Sequence service = shared-infra (ADJ-D07)
ADJ-F008 View adjustment detail Full header + lines + names + attribution RMS+RMH+WIDS365+market Implemented GetAdjustmentEndpoint.cs:84 Resolves Location/ReasonCode/Employee names + CreatedBy/UpdatedBy from CentralDb
ADJ-F009 List / filter / sort / search Paged list; filter location/status/reason/search; 7 sorts; Draft/Completed/Cancelled breakdown RMS+RMH+WIDS365+market Implemented ListAdjustmentsEndpoint.cs:117; breakdown :147-156 (#633) Breakdown spans the full filtered set in one grouped round-trip

T2 — Standard (market broadly expects) — weight ×2

ID Name Description Source Status Evidence Notes
ADJ-F010 Bulk / import / scan entry Add many lines fast — CSV/clipboard import or barcode-scan, not one-by-one WIDS365+RMS+market Missing Natural home: a bulk-add endpoint over InventoryAdjustmentLine + a portal import/scan surface QIIUB adds lines one at a time (bulk remove exists, #799; bulk add does not). WIDS365 has batch-JSON + clipboard/CSV; RMS Inventory Wizard 150; market has CSV + scan + mobile
ADJ-F011 Role / permission gating Only authorized roles can create/complete adjustments RMS+RMH+market Implemented Roles("SystemAdmin","Admin") on every endpoint; portal canTransition = Admin||Manager (AdjustmentDetailPage.tsx:63) Coarse RBAC (no per-location or per-reason grant) but the market-standard control is present
ADJ-F012 Reason categorization Preset reason set (damage / shrink / theft / found / recount) RMS+RMH+market Partial ReasonType='Adjustment' scopes the picker (ListReasonCodesEndpoint.cs:25; portal AdjustmentsListPage.tsx:70-74) What works: merchant-authored reasons scoped by ReasonType. Missing: no enforced category enum (shrinkage/theft/found are free-text, same as RMS/RMH). NB the ADJ-DAMAGE/ADJ-SHRINK codes ship only as DevSeed fixtures, not product presets
ADJ-F013 Adjustment history / audit Who/when + an append-only movement trail per adjustment RMS+RMH+WIDS365+market Implemented InventoryMovement (append-only, ReferenceType=InventoryAdjustment); CreatedBy/UpdatedBy (BaseEntity.cs:14-15) surfaced in Get/List Ledger + user attribution = the ADR-0023 document-trail tier. (WIDS365 additionally uses temporal tables; QIIUB deliberately does not on the movement ledger — ADR-0023.)
ADJ-F014 Operator attribution Record the specific employee (or completing user) on the adjustment RMS+RMH+WIDS365+market Missing EmployeeId/ClosedByEmployeeId modeled + surfaced but never written (InventoryAdjustment.cs:16,22) Reserved schema, no writer → Missing (status def). Aggravated: Complete/Cancel flip via ExecuteUpdateAsync, which bypasses the audit interceptor, so not even UpdatedByUserId is stamped on the transition (the base attribution credited to F013 covers create/edit only). See §8
ADJ-F023 Barcode-scan / mobile entry Add adjustment lines by scanning, or from a mobile device market Missing Line entry is manual desktop only (AdjustmentLineEntryBar.tsx); natural home: a scan handler + mobile surface Market table-stakes; unfolded from ADJ-F010 so the import/scan/mobile lines map 1:1 like the rest of the table
ADJ-F024 Live on-hand at line entry Show the item's current QuantityOnHand while entering the line WIDS365+market Missing Entry bar takes qty blind; natural home: resolve LocationProduct.QuantityOnHand into the line-entry response WIDS365 surfaces available-on-hand at entry — lets the operator adjust to a known figure

T3 — Advanced / Differentiator — weight ×1

ID Name Description Source Status Evidence Notes
ADJ-F015 Value / cost revaluation Adjust on-hand cost/value (revalue), not just quantity market Missing Lines are quantity-only; LocationProduct.Cost never re-weighted at Complete (CompleteAdjustmentEndpoint.cs:180-183) ERP tier — Cin7 explicit revaluation, NetSuite worksheet, Odoo. Not in Square/Clover/Lightspeed/WIDS365
ADJ-F016 Reversal / undo One-click reverse of a Completed adjustment (auto-offset) market Missing No endpoint; Completed is terminal. Natural home: a "reverse" endpoint that mints an offsetting Draft Today the operator manually creates an offsetting adjustment. Some ERP/mid-market offer a void/reverse
ADJ-F017 Approval / threshold gating Require sign-off (or a dollar threshold) before Complete market Missing Complete open to any Admin/SystemAdmin; no threshold. Natural home: a status/approval gate on the transition Rare even in ERP (NetSuite has no native approval) — building it would meet-or-beat the market
ADJ-F018 Mandatory-note enforcement Force a free-text note when the reason demands it market+QIIUB-original Missing ReasonCode.RequiresNote exists (ReasonCode.cs:13) but no adjustment endpoint enforces it Reserved flag, unwired → Missing. Cheap quick-win over existing schema
ADJ-F019 Attachment / photo evidence Attach a photo/document to a damage/shrinkage write-off market Missing Not in entity or endpoints. Natural home: a generic attachment table keyed by (ReferenceType, ReferenceId) Compliance-grade write-off evidence; present in some mid-market inventory apps
ADJ-F020 GL / accounting posting Post a journal entry (shrinkage expense / COGS) per adjustment market Missing No accounting integration on adjustments ERP tier (NetSuite/Cin7). RMS/RMH also lack per-adjustment GL (batch close-out export only) — QIIUB is at parity with the reference systems here, behind only ERP
ADJ-F021 Back-date / effective date Set an adjustment's effective date for period accounting market+RMS Missing AdjustmentDate = UtcNow at create, not user-settable (CreateAdjustmentEndpoint.cs) ERP period-close nicety
ADJ-F022 Discontinued-item write-off Adjust/write-off a product that is inactive/discontinued RMS+market Implemented Adjustment line variant resolution never joins the productActiveStatus filter (it sits on Product), so a killed SKU can still be lined; GetAdjustmentEndpoint.cs:98-99 keeps it visible in detail You can clear the last units of a discontinued SKU
ADJ-F025 Printable adjustment document Print / export the adjustment as a document RMS+WIDS365 Missing No print/PDF surface (repo-wide ADR-0070 print gap); natural home: the ADR-0070 print pipeline Internal doc — lower need than a PO/transfer slip, hence T3
ADJ-F026 Header valuation total Show the adjustment's total quantity / value magnitude WIDS365 Missing No aggregate on the header; natural home: a derived total in the Get/List projection WIDS365 surfaces valuation totals on the header
ADJ-F027 Damage quarantine / hold bin Hold damaged stock in a non-sellable state, optionally return-to-main RMS+RMH Missing QIIUB models damage as a destructive reason-coded write-off only; natural home: a location/stock-state flag RMS/RMH InventoryOffline offers hold + return-to-main; QIIUB meets only the dispose half (reclassified from N/A after the Fable pass)

Dependencies (excluded from score — listed so the boundary is visible):

ID Capability Owner Note
ADJ-D01 ReasonCode catalog (CRUD, merchant-scoped) Reason Codes (cross-cutting) Features/ReasonCodes/**; shared with Return/Void/Discount/PriceOverride/AR (ReasonCode.cs:5-6)
ADJ-D02 Cycle-count variance → auto-adjustment Stock Counts FinalizeStockCountEndpoint.cs:118-237 (movement Count, reason CYCLE-COUNT)
ADJ-D03 Damage-on-receive write-off Transfers TransferDamageAdjustmentService.cs (reason ADJ-XFR-DAMAGE)
ADJ-D04 Receiving quantity/cost correction Receivings Receipt Complete/Cancel posts its own Receipt movement
ADJ-D05 InventoryMovement ledger + LocationProduct stock Inventory core InventoryMovement.cs; the stock row Complete upserts
ADJ-D06 Shrinkage / variance-by-reason reporting Reports Adjustments supplies the filterable list (ADJ-F009); the aggregate $ report is Reports'
ADJ-D07 Document sequence service shared-infra IDocumentSequenceService; the use is scored ADJ-F007

N/A — not applicable to QIIUB (excluded; reason given):

ID Capability Why N/A
ADJ-N01 Sync push/pull of the adjustment document (offline POS) Adjustments are authored web-side (back-office); propagation of the resulting LocationProduct change to offline devices is the Sync module's job, not an adjustment feature. Met-differently-by-architecture.
ADJ-N02 HQ/Central-originated adjustment (RMS Type=8) QIIUB runs one cloud database; a merchant-wide user adjusts any location directly, so there is no HQ/Central-vs-store adjustment split. Same call as the PO-Planner / Distribution HQ N/As.

4. Storage specification

InventoryAdjustment (aggregate root) — src/QIIUB.Domain/Merchants/InventoryAdjustment.cs

InventoryAdjustmentLine (editable child) — InventoryAdjustmentLine.cs

Referenced (not owned): ReasonCode (→ Reason Codes doc), InventoryMovement + LocationProduct (→ Inventory core). MerchantId-first composite FKs verified throughout (Critical Rule #1).


5. API surface

Surface Verb + Route Impl (file:line) Realizes Roles Notes
API POST /adjustments CreateAdjustmentEndpoint.cs:103 F001–F003, F007 SysAdmin/Admin Draft + optional lines; snapshots cost/price
API POST /adjustments/{id}/lines AddAdjustmentLineEndpoint.cs:60 F005 SysAdmin/Admin 409 if not Draft
API PUT /adjustments/{aid}/lines/{id} UpdateAdjustmentLineEndpoint.cs:62 F005 SysAdmin/Admin qty+notes; route-forgery check
API DELETE /adjustments/{aid}/lines/{id} RemoveAdjustmentLineEndpoint.cs:30 F005 SysAdmin/Admin hard delete
API POST /adjustments/{aid}/lines/batch-delete RemoveAdjustmentLinesEndpoint.cs F005 SysAdmin/Admin atomic bulk-remove, ≤100 (#799)
API PUT /adjustments/{id} UpdateAdjustmentEndpoint.cs F003 SysAdmin/Admin header only (reason+notes); Location locked
API POST /adjustments/{id}/complete CompleteAdjustmentEndpoint.cs:77 F004, F006 SysAdmin/Admin the posting op; 400 if 0 lines
API POST /adjustments/{id}/cancel CancelAdjustmentEndpoint.cs F006 SysAdmin/Admin no inventory effect
API GET /adjustments/{id} GetAdjustmentEndpoint.cs:84 F008, F022 SysAdmin/Admin discontinued-item safe
API GET /adjustments ListAdjustmentsEndpoint.cs:117 F009 SysAdmin/Admin filter/sort/search + breakdown
portal Inventory → Adjustments (list + detail + drawer + line bar + complete/cancel modals) apps/qiiub-portal/src/features/adjustments/** F001,F004–F009,F011 Admin/Manager backend + UI in lockstep

No over-build (every endpoint maps to a feature). UI gap: the header-edit endpoint (UpdateAdjustment) exists + useUpdateAdjustment is wired, but the detail page does not surface header edit (its comment "there is no Update endpoint" is stale — §8). Endpoint count (10) is size context, not a metric.


5b. Validations inventory

Absent — business validations (verified not present):

Missing validation Effect today Tracked as
RequiresNote enforcement a reason that "requires" a note can be used with none ADJ-F018
Approval / dollar-threshold on Complete any Admin completes any adjustment, no ceiling ADJ-F017
Negative-on-hand guard a decrease can drive QuantityOnHand below 0 unremarked §7 hardening bundle

5c. Test surface & confidence

Score says "how complete vs a mature POS"; this says "how trustworthy is the built part." Testedness never enters §6.

Flow Tested
Create + Complete → LocationProduct updated (80−5=75) ✓ (:216-245)
Two lines same variant, no existing LP → aggregate (SQL-2601 regression) + new LP Price NULL ✓ (:247-307)
Complete of a 0-line draft → 400 ✗ (not named)
Cancel: flips + no movements + already-Completed/Cancelled → 409 ✓ (:875,:900,:925,:944)
List filter/sort/search + status breakdown ✓ (:309–827)
Cross-merchant isolation (merchant B → 404) ✓ (:696-712)
Get includes attribution ✓ (:849)
AddLine / UpdateLine / RemoveLine happy+sad (direct) ✗ (exercised only via create-with-lines)
RequiresNote behavior ✗ (feature not built)

Named test gaps → one §7 "test hardening" row: direct line-management sad paths; explicit 0-line-Complete 400.


6. Scoring rubric (mechanical)

Weights T1=3, T2=2, T3=1; Implemented=1.0, Partial=0.5, Missing=0.0; Dependency/N/A excluded.

Tier Impl Partial Missing Dep-excl Scored Σ value tier%
T1 (×3) 9 0 0 9 9.0 100.0
T2 (×2) 2 1 4 7 2.5 35.7
T3 (×1) 1 0 10 11 1.0 9.1
Excluded 7 Dep + 2 N/A
overall% = 100 × ( 3×9.0 + 2×2.5 + 1×1.0 ) / ( 3×9 + 2×7 + 1×11 )
         = 100 × ( 27 + 5 + 1 ) / ( 27 + 14 + 11 )
         = 100 × 33 / 52 = 63.5%  → 63%

Overall = 63% (T1 100 / T2 36 / T3 9). 27 scored features + 7 Dependency + 2 N/A = 36 mapped IDs. This is the post-Fable number — the first synthesis read 76%; the adversarial pass corrected the F014 double-count, three unreconciled source lines (F024/F026 + F023 unfold), and the over-generous damage-bin N/A (→ F027), dropping it to 63%.

Flat-Partial caveat: the one remaining T2 Partial (F012 reason categorization) is "core-need-met, refinement-missing" — not thin. Anti-gaming guards: (a) tiers by market necessity — the T3 sparsity mirrors the market's own ERP-only set; (b) no double-count — the Fable pass caught one: F014 had borrowed the base CreatedBy/UpdatedBy infra already credited to F013, and is now Missing (reserved EmployeeId alone can't earn Partial); bulk-remove is folded into F005, bulk-add is the separate gap F010; F007's sequence service is a dep, only its use is scored; (c) no Dependency/N/A hides an in-module gap — the damage-bin was reclassified N/A→Missing (F027); the two remaining N/As are architecture/scope; the three auto-adjustment writers genuinely belong to neighbors; (d) every Implemented has file:line, every Partial names what's missing; (e) §9 reconciles all four source families (fixed after the pass found three dropped lines); (f) single-owner verified vs the four movement-family siblings + Stock Counts.

Reproducibility honesty. The denominator (36 mapped rows) freezes at this first synthesis; a re-score updates statuses only. Family ranking: PO 74 / Rcv 67 / Adj 63 / Trf 60 / Dist 58 — third. Adjustments' entire table-stakes tier is built (T1 100), but the T2/T3 breadth (bulk/scan entry, live-on-hand, operator attribution, reversal, revaluation, approval) is where a mature POS pulls ahead.


7. Gap list & recommendations

Rank Gap (ID) Tier Impact Recommendation ADR?
1 ADJ-F014 operator attribution T2 No POS-employee accountability on write-offs (loss-prevention gap) Quick win — write EmployeeId/ClosedByEmployeeId from context on create/complete; fields + response already exist No
2 ADJ-F018 mandatory-note T2/T3 "requires note" reasons don't actually require one Quick win — enforce ReasonCode.RequiresNote in Create/Complete validators No
3 ADJ-F010 bulk / import / scan T2 Large write-offs / recounts are slow line-by-line Add a bulk-add endpoint over InventoryAdjustmentLine + portal import/scan No (extends model)
4 ADJ-F016 reversal / undo T3 Fixing a wrong Completed adjustment is a manual offset A reverse endpoint that mints an offsetting Draft referencing the original No (extends model)
5 ADJ-F017 approval / threshold T3 No control on high-value adjustments Approval gate on the Draft→Completed transition (meets-or-beats market) Requires ADR (new transition/state)
6 ADJ-F015 / F020 / F021 value-revaluation / GL / back-date T3 ERP-tier accounting not served Bundle — revisit when an accounting/GL vertical is scoped Requires ADR
7 Test hardening Line-management sad paths + 0-line-Complete unguarded by name Add the §5c ✗ flows No

7a. GHES issue coverage

Searched open issues (adjustment / reversal / revaluation / shrinkage / write-off) at measurement: no open issue tracks any of these gaps. #289 PublicId Audit Phase 2 is tangential (touches many modules). All Adjustments gaps are currently untracked — when a dev opens a ticket for one, reference the stable ID (e.g. ADJ-F014) in the issue body so this section can link gap ↔ ticket on the next re-score. Candidates to file first: the two quick wins (ADJ-F014, ADJ-F018).


8. Open questions & contradictions


9. Source reconciliation (denominator integrity)

Every capability in the 4-source inventory (artifact-adjustments-gathering-{rmhrms,wids365,market}.md) + the QIIUB-original sweep mapped to a disposition. scored = own §3 row; folded = subsumed; N/A = out of scope; dep = neighbor.

Source inventory line Disposition Where
Manual single-item quantity adjustment scored ADJ-F001/F002
Signed delta vs target count scored ADJ-F002
Reason code required on adjustment scored ADJ-F003
Post to on-hand + movement ledger scored ADJ-F004
Add/edit/remove lines scored ADJ-F005
Open→Closed / Draft→Commit lifecycle (WIDS365/RMS) scored ADJ-F006
Document number (WIDS365 AdjustmentHeader, RMS) scored ADJ-F007
View / list adjustments scored ADJ-F008/F009
Batch/JSON + clipboard/CSV import (WIDS365); Inventory Wizard 150 (RMS) scored (Missing) ADJ-F010
Barcode-scan / mobile adjustment entry (market) scored (Missing) ADJ-F023
Live available-on-hand shown at line entry (WIDS365) scored (Missing) ADJ-F024
Header quantity / valuation totals (WIDS365) scored (Missing) ADJ-F026
Printable adjustment document (RMS/WIDS365 DevExpress report) scored (Missing) ADJ-F025
Role / permission gating (market table-stakes) scored ADJ-F011
Preset reason categories damage/theft/loss/recount (market); RMS/RMH free-text type-2 scored (Partial) ADJ-F012
Adjustment history / audit trail; WIDS365 temporal tables scored ADJ-F013
Operator/cashier on the adjustment (all) scored (Missing) ADJ-F014
Value/cost revaluation (Cin7/NetSuite/Odoo) scored (Missing) ADJ-F015
Reversal / void of a posted adjustment scored (Missing) ADJ-F016
Approval workflow (rare; NetSuite none) scored (Missing) ADJ-F017
Mandatory note per reason scored (Missing) ADJ-F018
Attachment / photo evidence scored (Missing) ADJ-F019
GL / journal posting per adjustment (ERP) scored (Missing) ADJ-F020
Back-date / effective date (ERP/RMS) scored (Missing) ADJ-F021
Adjust discontinued/inactive item scored ADJ-F022
Reason-code catalog / configuration (RMS Options, WIDS365 LK_AdjustmentReason) dep ADJ-D01
Physical/cycle count → variance posting (RMS Calculate→Commit; market count→adjust) dep ADJ-D02
Damage-on-receive write-off dep ADJ-D03
Damage hold/quarantine bin + return-to-main (RMS/RMH Offline Inventory) scored (Missing) ADJ-F027
Receiving cost/qty correction dep ADJ-D04
Movement ledger (RMS InventoryTransferLog Type 5–9; WIDS365 InventoryTransferLog) dep ADJ-D05
Shrinkage / variance reporting (market shrinkage reports) dep ADJ-D06 — contestable: the in-module list gives a status breakdown (F009); a by-reason/$ shrinkage report is assigned to Reports. Scoring it in-module Missing T2 would drop the overall ~3pts. Kept Dependency per single-owner (Reports owns reporting); flagged for a human
HQ/Central adjustment (RMS Type=8, Worksheet 307) N/A ADJ-N02
Sync of the document to offline POS N/A ADJ-N01
Auto-reconcile concurrent movement during count (RMH refinement) dep ADJ-D02 (Stock Counts)

No source line is left unreconciled across the 4 source families (RMS/RMH + WIDS365 + market + QIIUB-original) — the Fable pass added four previously-dropped lines (ADJ-F023/F024/F025/F026) and reclassified the damage bin (ADJ-F027).


Appendix — reproducibility checklist for the next session