At a Glance
Persona: Finance (Officer / AP Clerk + Finance Manager / Controller) · Module: good-receive-note · Scenarios: ~30
Categories: Happy Path · Permission · Validation · Edge Case
E2E coverage: maps to501-grn.spec.tsin../carmen-inventory-frontend-e2e/
This page captures the test scenarios that the Finance persona (the Finance Officer / AP Clerk at the day-to-day three-way match desk plus the Finance Manager / Controller at the period-close sign-off boundary) directly drives in the good-receive-note module. Finance is a post-commit participant — entry to this flow presupposes that the Inventory Manager has already fired the saved → committed transition on the Receiver path, which has already raised the inventory accrual (Dr Inventory / Cr GRN Clearing, GRN_POST_006) and incremented on-hand. Finance's involvement covers two distinct activities: pre-AP financial adjustment on committed GRNs (correcting extra-cost allocation methods — manual, by_value, by_qty per enum_allocate_extra_cost_type — and tax codes while the vendor invoice has not yet arrived; allowed by GRN_AUTH_007); and three-way match when the invoice arrives (matching PO ↔ GRN ↔ Invoice on qty and price within tenant tolerance, posting the AP-side journal Dr GRN Clearing / Cr AP-Trade on success per GRN_POST_008, flagging the discrepancy back to the Purchaser on failure per GRN_POST_009). The Finance Manager additionally runs period-close sign-off — reconciling the inventory sub-ledger against the GL inventory control account, ageing open GRN Clearing balances, and locking the period. Critically: the GRN's doc_status enum is not transitioned by Finance — saved → committed is the only posting event the document undergoes; match outcome lives on a separate match flag, not on the four-state enum. Scenarios are grouped into happy paths (pre-AP allocation adjust, clean three-way match, partial GRN match, price-within-tolerance auto-pass, FX adjustment, period-close sign-off), permission (pre-AP adjust allow, three-way match allow, AP post allow, override-failed-match deny, Finance ≠ Purchaser/Receiver SoD, period-close lock by Finance Manager), validation (negative tests against discrepancy flagging, missing GRN, voided GRN, multi-invoice splits, closed-period blocks, duplicate invoice match), and edge cases around tolerance boundaries, FX rate equality, multi-GRN single-invoice consolidation, concurrent invoice posts, and decimal precision on AP amounts. Cross-persona handoffs that pivot off Finance (Finance ↔ Purchaser bounce-back on flagged discrepancies, Finance ↔ Controller at period close) live in 04-test-scenarios.md.
| # | Scenario | Pre-condition | Steps | Expected |
|---|---|---|---|---|
| FIN-HP-01 | Pre-AP extra-cost allocation adjust — manual mode |
GRN G-1 at doc_status = committed (raised by Inventory Manager); vendor invoice not yet arrived; match flag = unmatched; one tb_extra_cost row (freight, net_amount = ฿200.00) currently at allocate_extra_cost_type = by_value; Finance Officer finance@blueledgers.com logged in with GRN_AUTH_007 permission; carrier invoice attached as evidence on the extra-cost row. |
1. Open G-1 from the Pending Match worklist. 2. Open the extra-cost panel; review the existing by_value per-line allocations finalised at commit. 3. Switch allocate_extra_cost_type from by_value to manual. 4. Enter per-line allocations: line 1 = ฿150.00, line 2 = ฿50.00 (sum = ฿200.00, exact). 5. Click Save adjusted snapshot. |
Switch persists; GRN_CALC_009 validates sum ≤ ฿0.01 tolerance of tb_extra_cost.net_amount — pass; per-line allocation snapshot rewritten; Last Cost per line recomputed per GRN_CALC_012 (line 1 = (line1.net_amount + 150.00) / qty, line 2 = (line2.net_amount + 50.00) / qty); compensating GL entry posted for the delta in inventory cost vs the original by_value snapshot (Dr/Cr Inventory ↔ GRN Clearing for the cost delta); GRN doc_status stays committed; activity log records { action: 'allocation_adjusted', user: finance, delta_amount: ... }. |
| FIN-HP-02 | Pre-AP extra-cost allocation adjust — by_value mode |
GRN G-2 at doc_status = committed; match flag = unmatched; extra cost ฿200.00 currently at allocate_extra_cost_type = manual; two lines with line1.net_amount = ฿1,192.25, line2.net_amount = ฿356.00; Finance Officer logged in. |
1. Open G-2. 2. Open the extra-cost panel. 3. Switch from manual to by_value. 4. Confirm system computes per GRN_CALC_010: line 1 = Round(200.00 × (1,192.25 / 1,548.25), 2) = ฿154.01; line 2 = remainder ฿45.99. 5. Click Save adjusted snapshot. |
Allocation recomputed deterministically; last line absorbs the rounding remainder so Σ allocations = ฿200.00 (within ฿0.01); Last Cost per line recomputed; compensating GL entry posted for the delta; doc_status stays committed; activity log records the method change. |
| FIN-HP-03 | Pre-AP extra-cost allocation adjust — by_qty mode |
GRN G-3 at doc_status = committed; match flag = unmatched; extra cost ฿200.00; two lines with line1.received_base_qty = 10.000, line2.received_base_qty = 4.000 (in base UoM); Finance Officer logged in. |
1. Open G-3. 2. Open the extra-cost panel. 3. Switch to by_qty. 4. Confirm per GRN_CALC_011: line 1 = Round(200.00 × (10.000 / 14.000), 2) = ฿142.86; line 2 = remainder ฿57.14. 5. Click Save adjusted snapshot. |
Allocation recomputed using base-UoM qty (lines may use different receiving UoMs); Σ allocations = ฿200.00; Last Cost per line recomputed via GRN_CALC_012; compensating GL entry posted; doc_status stays committed. |
| FIN-HP-04 | Clean three-way match — AP posted on success | GRN G-4 at doc_status = committed, match flag = unmatched; PO PO-4 line counters in sync with GRN; vendor invoice INV-4 arrives via AP intake with qty and price matching GRN line-for-line within tenant tolerance (e.g. price tolerance = 2%, qty tolerance = 0); GRN Clearing balance = ฿100,000 at the GRN's base_net_amount + allocated_extra_cost. |
1. AP intake captures INV-4 and auto-deep-links into the GRN match screen for (vendor_id, po_no = PO-4, invoice_no = INV-4). 2. System pairs invoice lines to GRN lines via purchase_order_detail_id. 3. Run the match per GRN_POST_007. 4. All lines pass qty equality and price tolerance. 5. Click Post AP. |
Atomic match: re-check against PO-4 line's order_qty and order_unit_price (no upstream drift); journal posted per GRN_POST_008 — Dr GRN Clearing ฿100,000 / Cr AP-Trade ฿100,000 clearing the accrual against vendor AP liability; tax accruals on input-tax control reconciled to invoice tax; GRN match flag flips unmatched → matched; invoice posts to AP for payment cycle; GRN doc_status stays committed (no enum transition per GRN_POST_008); inventory sub-ledger unchanged; activity log records { action: 'ap_posted', invoice_no: 'INV-4' }. Maps to TC-GRN-130001 (Financial Summary — Happy Path). |
| FIN-HP-05 | Partial GRN match against received-only qty | GRN G-5 at doc_status = committed from a partial receipt (received_qty = 6 against PO order_qty = 10); match flag = unmatched; vendor invoice INV-5 arrives billing qty = 6 (matching the partial receipt, not the full PO order qty) at correct price. |
1. AP intake captures INV-5. 2. System pairs against G-5 (not against PO pending qty). 3. Run the match — qty strict equality invoice.qty = GRN.received_qty = 6 passes; price within tolerance passes. 4. Click Post AP. |
Match clean on the received-only basis; journal Dr GRN Clearing / Cr AP-Trade posts at the matched amount only; G-5 match flag → matched; the remaining 4 units on PO-5 are not part of this match (they sit in the PO pending balance awaiting a second GRN); when a follow-up GRN commits the remaining 4, a separate invoice will match against it; doc_status of G-5 stays committed. Maps to TC-GRN-110004 (partial-received GRN match leg). |
| FIN-HP-06 | Price within tolerance — auto-pass with variance absorbed | GRN G-6 at doc_status = committed, match flag = unmatched; tenant price tolerance configured = 2%; vendor invoice INV-6 arrives with line price ฿128.00 vs GRN base_price = ฿125.50 (delta = +฿2.50, ≈1.99% — within tolerance). |
1. AP intake captures INV-6. 2. Run the match per GRN_POST_007. 3. System computes price gap per line: (128.00 − 125.50) / 125.50 ≈ 1.99% ≤ 2%. 4. Auto-pass without Purchaser handoff. 5. Post AP. |
Match auto-passes; AP posts at the invoice price ฿128.00 × qty; the price gap absorbed into a price-variance account (or capitalised into inventory per tenant policy) on the AP-clearing leg — e.g. Dr GRN Clearing (฿125.50 × qty) / Dr Price Variance (฿2.50 × qty) / Cr AP-Trade (฿128.00 × qty); match flag → matched; no Purchaser handoff (per Section 3 of 03-user-flow-finance.md, price-within-tolerance is decision-branched away from the bounce-back). |
| FIN-HP-07 | FX adjustment on currency mismatch / rate movement | GRN G-7 at doc_status = committed with snapshot currency = USD, exchange_rate = 36.00000 (USD/THB) captured at receipt; base amount = ฿360,000.00 for invoice line $10,000.00; vendor invoice INV-7 arrives with same $10,000.00 line but invoice posting date FX rate is now 36.50000. |
1. AP intake captures INV-7. 2. System detects FX mismatch between GRN snapshot rate and current AP-posting-date rate. 3. Match the line on transaction-currency amount ($10,000.00, equal) — qty and price pass tolerance. 4. Post AP at the AP-posting-date rate. |
Match passes on transaction-currency comparison (GRN_CALC_008 base conversion uses GRN's stored snapshot rate; FX comparison happens at AP posting time); journal posted in base currency at the new rate — Dr GRN Clearing ฿360,000.00 (at GRN snapshot rate) / Dr FX Loss ฿5,000.00 (delta) / Cr AP-Trade ฿365,000.00 (at AP posting rate); FX variance posted to the FX Gain/Loss account per tenant policy; match flag → matched; GRN snapshot rate not retroactively edited. |
| FIN-HP-08 | Period-close reconciliation and sign-off | Closing period 2026-04; Finance Manager finance.mgr@blueledgers.com logged in with period-lock authority; all committed GRNs in period are either matched within period or aged with documented justification; inventory sub-ledger total = GL inventory control account total (variance = 0). |
1. Open the period-close dashboard. 2. Review GRN Clearing aging report (oldest open balance, total open count). 3. Run the inventory-sub-ledger-vs-GL reconciliation report. 4. Review the unmatched-GRN exception list; confirm justification on each. 5. Click Lock period 2026-04. | All reconciliation reports pass with zero variance; GRN Clearing aging shows expected balances; period-lock fires per tenant policy; subsequent AP-post attempts against 2026-04-dated documents are rejected (see FIN-VAL-06); open exceptions roll forward to 2026-05's Pending Match worklist; activity log records { action: 'period_locked', period: '2026-04', user: finance_manager }. |
| # | Scenario | Expected behaviour (allow/deny + reason) |
|---|---|---|
| FIN-PERM-01 | Finance Officer adjusts extra-cost allocation pre-AP-posting | Allow. GRN_AUTH_007 permits Finance Officer / AP Clerk to adjust the allocation while doc_status = committed and before the three-way match has cleared the GRN to AP. The allocation panel is editable; the method switch (manual / by_value / by_qty) and per-line amount overrides are enabled. The header on stock-impacting fields (vendor, currency, exchange rate, receipt date, line quantities) remains read-only. Maps to FIN-HP-01..03. |
| FIN-PERM-02 | Finance Officer runs three-way match | Allow. Finance Officer owns the match flow per Section 2.2 of 03-user-flow-finance.md. Match screen is enabled on committed GRNs with match flag unmatched or partially_matched; the system pairs invoice lines to GRN lines via purchase_order_detail_id; qty and price comparisons run server-side; the Post AP button is enabled on clean-match results. |
| FIN-PERM-03 | Finance Officer posts the AP-clearing journal on match success | Allow. GRN_POST_008 AP-side leg (Dr GRN Clearing / Cr AP-Trade) is authorised to the Finance Officer / AP Clerk role. The atomic match transaction fires on Post AP click and clears the accrual against the vendor AP liability. Tax-side reconciliation against the input-tax control account is part of the same transaction. Maps to FIN-HP-04. |
| FIN-PERM-04 | Finance Officer attempts to override a failed match and force-post AP | Deny — Finance Manager required. A Finance Officer cannot bypass a flagged discrepancy and force AP to post. The Override and Post action is hidden / disabled for the Finance Officer role; a direct API call returns "Override of flagged three-way match requires Finance Manager role."; the GRN stays at committed with match flag flagged; no AP-clearing journal posts. The Finance Manager is the only role permitted to force-post (with audit-grade justification) or, more commonly, to authorise the credit-note path (tb_credit_note) per GRN_XMOD_007. |
| FIN-PERM-05 | Segregation of duties — Finance ≠ Purchaser AND Finance ≠ Receiver | Deny when same user. The user posting the three-way match (last_action_by_id on the AP-clearing journal) MUST NOT be the same user who created or transmitted the upstream PO (tb_purchase_order.buyer_id or PO in_progress → sent actor) and MUST NOT be the same user who committed the GRN (saved → committed actor on tb_good_received_note). The match call rejects at the Post AP step with "Three-way match must be posted by a user separate from the PO transmitter and the GRN committer (SoD)."; no journal entry is written; no match-flag flip. Extends GRN_AUTH_010 (PO_AUTH_010 mirror on the GRN side) into the AP step. |
| FIN-PERM-06 | Finance Manager locks a closed period | Allow. Period-lock authority sits with the Finance Manager role per Section 2 / Section 4 of 03-user-flow-finance.md. The period-close dashboard's Lock period button is enabled only for Finance Manager (and System Administrator on audit grounds); Finance Officer sees the dashboard read-only. After lock, AP-post attempts against the locked period are rejected per FIN-VAL-06; reversing a period-lock requires elevated co-authorisation (Finance Manager + Controller) and is out of scope for this page. |
| FIN-PERM-07 | Finance Officer attempts to edit GRN header / line on a committed GRN |
Deny — terminal lock + role scope. Per GRN_AUTH_002 and the lifecycle, committed is locked against header / line edits for all roles. Finance's permission scope on committed GRNs is limited to extra-cost allocation, tax-code lines (is_tax_adjustment = true per GRN_VAL_010), and match-screen actions — NOT to qty, vendor, currency, exchange rate, or receipt date. The header / line edit endpoints reject Finance with "GRN at status committed is locked except for allocation and tax-code adjustments under GRN_AUTH_007."; corrections to stock-impacting fields go through tb_credit_note or inventory-adjustment. |
| # | Scenario | Trigger | Expected error |
|---|---|---|---|
| FIN-VAL-01 | Qty discrepancy flagged back to Purchaser | GRN G-V1 at doc_status = committed with received_qty = 10 on line L1; vendor invoice INV-V1 arrives billing qty = 12 on the same line (vendor over-billed by 2 units). |
Flag back to Purchaser — GRN_POST_009. Match screen reports qty mismatch (strict equality required, no negative tolerance per Section 2.2 of 03-user-flow-finance.md); AP holds INV-V1 in disputed state; a system comment is appended on G-V1 and on PO-V1 recording discrepancy type = qty, gap = +2, invoice ref = INV-V1; match flag flips unmatched → flagged; doc_status stays committed (no enum transition); the flagged GRN routes to Purchaser for vendor-side resolution (credit-note negotiation for the 2-unit over-bill). |
| FIN-VAL-02 | Price discrepancy outside tolerance flagged back to Purchaser | GRN G-V2 at doc_status = committed, line price ฿125.50; tenant price tolerance = 2%; vendor invoice INV-V2 bills ฿135.00 (delta = +฿9.50, ≈7.57% — outside tolerance). |
Flag back to Purchaser — GRN_POST_009. Match screen reports price mismatch outside tolerance; AP holds INV-V2 in disputed; system comment on G-V2 and PO-V2 recording type = price, gap = +฿9.50, invoice ref = INV-V2; match flag → flagged; GRN stays at committed; Purchaser owns vendor-side resolution and may raise a [vendor-pricelist](/en/inventory/vendor-pricelist) amendment so future POs price correctly. |
| FIN-VAL-03 | Invoice arrives before GRN — missing GRN cannot match | Vendor invoice INV-V3 arrives via AP intake at T; no committed GRN exists for (vendor_id, po_no = PO-V3) at T (receipt has not happened yet — invoice ahead of receipt). |
Hold invoice at awaiting_receipt — per the missing-GRN decision branch in Section 3 of 03-user-flow-finance.md. AP returns "No committed GRN found for PO-V3; invoice held in awaiting_receipt state."; no match runs; no AP-clearing journal; AP module re-polls on each subsequent GRN commit against PO-V3; the awaiting-receipt sweep runs on tenant-scheduled cadence to retry the match when a GRN later commits. |
| FIN-VAL-04 | Invoice for voided GRN rejected | GRN G-V4 was voided pre-commit (saved → voided); the receipt event never posted; vendor invoice INV-V4 arrives keyed against (vendor_id, G-V4-related-PO). |
Reject the match attempt. Match candidate scan per Section 2.2 excludes voided GRNs (only committed with match flag unmatched or partially_matched are eligible); server returns "Cannot match invoice INV-V4 to GRN G-V4 — GRN is voided; voided GRNs cannot post AP."; the invoice routes to AP-investigation queue; resolution requires either re-keying the invoice against the correct (committed) GRN, or raising a fresh GRN if the physical receipt is to be re-recorded, or refusing the invoice with the vendor. |
| FIN-VAL-05 | Multi-invoice partial-then-full match against one GRN | GRN G-V5 at doc_status = committed, received_qty = 10 on a single line worth ฿100,000; match flag = unmatched; vendor sends invoice INV-V5a billing qty = 6, amount = ฿60,000 then later sends INV-V5b billing qty = 4, amount = ฿40,000 (split-billing N:1). |
OK — partial then full. First invoice match: pairs against G-V5 for the first 6 units; AP-clearing partial post — Dr GRN Clearing ฿60,000 / Cr AP-Trade ฿60,000; residual GRN Clearing balance ฿40,000 stays open; match flag flips unmatched → partially_matched. Second invoice match: pairs against the residual 4 units; AP-clearing residual post — Dr GRN Clearing ฿40,000 / Cr AP-Trade ฿40,000; match flag flips partially_matched → matched; residual cleared; doc_status of G-V5 stays committed throughout. |
| FIN-VAL-06 | AP post against a closed period rejected | Period 2026-04 is locked (FIN-HP-08); vendor invoice INV-V6 arrives in 2026-05 but is dated 2026-04-25 (invoice date inside closed period); Finance Officer attempts to post AP. |
Reject at AP-post. Server returns "AP cannot post to period 2026-04 — period is locked."; no match journal fires; match flag stays at its prior value (unmatched or partially_matched); the Finance Officer re-keys the invoice with a current-period posting date (and a 2026-04 document date if statute requires), or routes to Finance Manager to re-open the period under audit controls. |
| FIN-VAL-07 | Duplicate invoice match rejected | GRN G-V7 at doc_status = committed, match flag = matched (already AP-posted against INV-V7); the vendor or AP clerk submits the same INV-V7 a second time (re-key error, duplicate EDI feed). |
Reject the duplicate. GRN_VAL_005 ((invoice_no, vendor_id) uniqueness) and a parallel guard on the match flag (matched GRNs cannot re-match) combine to reject; server returns "Invoice INV-V7 has already been matched to GRN G-V7 and posted to AP. Duplicate match rejected."; no double-posting of Dr GRN Clearing / Cr AP-Trade; AP intake routes the duplicate to investigation queue. |
| FIN-VAL-08 | Match attempted on GRN with extra cost not fully allocated | GRN G-V8 at doc_status = committed (somehow committed despite incomplete allocation — e.g. data migration); tb_extra_cost.net_amount = ฿200.00 but persisted per-line allocations sum to ฿180.00 (gap ฿20.00); invoice arrives. |
Reject match — allocation incomplete. GRN_VAL_014 is a commit-time block but the match path also re-checks allocation sum integrity; server returns "GRN G-V8 has unallocated extra costs (gap ฿20.00). Complete allocation before posting AP."; Finance must run FIN-HP-01..03 to bring Σ allocations within ฿0.01 of tb_extra_cost.net_amount (per GRN_CALC_009–GRN_CALC_011) before re-attempting the match. |
| FIN-VAL-09 | Manual allocation sum does not match extra-cost net | GRN G-V9 at doc_status = committed, match flag = unmatched; Finance switches to manual allocation and enters per-line amounts summing to ฿199.50 against tb_extra_cost.net_amount = ฿200.00 (gap ฿0.50 > ฿0.01 tolerance). |
Reject at allocation save — GRN_CALC_009. Server returns "Manual allocation sum (฿199.50) does not equal extra-cost net amount (฿200.00) within tolerance (฿0.01)."; the per-line amounts are held in unsaved state; Finance must correct one line by ฿0.50 to bring the sum to exact equality (or within ฿0.01) before the save persists. |
| # | Scenario | Condition | Expected |
|---|---|---|---|
| FIN-EDGE-01 | Exact tolerance boundary on price AND qty | Tenant price tolerance = 2%; qty tolerance = 0; GRN line price ฿100.00, received_qty = 10; invoice line bills qty = 10 (exact) at ฿102.00 (delta = +2.00%, exactly at boundary). |
Auto-pass — within tolerance inclusive. Match treats the boundary as inclusive (≤ not <); (102.00 − 100.00) / 100.00 = 2.00% ≤ 2% passes; AP posts at invoice price; price variance ฿2.00 × 10 = ฿20.00 absorbed into price-variance account on the AP-clearing leg per FIN-HP-06 pattern; match flag → matched. Setting invoice price = ฿102.01 would breach the bound and route to FIN-VAL-02. |
| FIN-EDGE-02 | FX rate equals snapshot — no FX gain/loss | GRN G-E2 snapshot currency = USD, exchange_rate = 36.00000; invoice INV-E2 arrives at AP-posting-date rate exactly = 36.00000 (no rate movement). |
Match passes; no FX entry written. Base-currency comparison delta = 0; no FX Gain/Loss row in the AP-clearing journal — journal is the clean two-line Dr GRN Clearing ฿360,000.00 / Cr AP-Trade ฿360,000.00 at the equal rate; match flag → matched. No-op on FX is explicitly different from a journal with an FX leg of ฿0 — the FX line is not written at all. |
| FIN-EDGE-03 | Multi-GRN single-invoice consolidation (1:N) | Same vendor, same PO PO-E3; two committed GRNs against the same PO: G-E3a (received_qty = 6) and G-E3b (received_qty = 4); both at match flag unmatched; vendor consolidates billing into one invoice INV-E3 covering both receipts (qty = 10, full PO amount). |
Match consolidates 1:N. AP scopes candidate set per Section 2.2 by (vendor_id, po_no = PO-E3) finding both G-E3a and G-E3b; the system pairs invoice line qty 10 across both GRNs (6 + 4); qty and price pass per-GRN; AP-clearing journal posts in one atomic transaction clearing both GRN Clearing balances proportionally; both match flags flip unmatched → matched; PO-line received-qty counters unchanged (already advanced at each GRN's commit). |
| FIN-EDGE-04 | Concurrent invoice posts on the same GRN from two AP sessions | AP Clerk A and AP Clerk B (separate sessions) both open the match screen for G-E4 (match flag = unmatched) at T and T + 200ms; A clicks Post AP at T + 1s; B clicks Post AP at T + 1.2s. |
First post wins atomically. A's AP-clearing journal posts; match flag → matched; doc_version advances. B's submit is reconciled against the new state — optimistic-concurrency guard rejects B with "This GRN was matched by another user. Please refresh."; alternatively, if B's invoice number differs and the GRN is now matched, the duplicate guard (FIN-VAL-07) blocks; no double-posting of Dr GRN Clearing / Cr AP-Trade; no double-write to AP-Trade. |
| FIN-EDGE-05 | Decimal precision on AP amount with FX and rounding | Invoice line qty = 5.123 (3-dp qty precision) at unit price $12.34567 (5-dp rate-style precision); FX exchange_rate = 36.12345; transaction-currency line amount = Round(5.123 × 12.34567, 2); base amount = Round(line_amount × 36.12345, 2). |
Stored within Decimal precision; AP posts at rounded base. Per GRN_CALC_001 line subtotal at 2dp; per GRN_CALC_008 base conversion at 2dp using the 5-dp FX rate; intermediate computations always re-read the rounded prior step per Section 3 of 02-business-rules.md. The AP-Trade credit posts at the rounded base amount; rounding drift between the GRN snapshot and the AP-post computation (sub-cent) is absorbed per tenant policy (price-variance account, no separate journal); no Decimal(20, 5) overflow. Mirrors RCV-EDGE-02 on precision but on the AP-amount path rather than the lot-qty path. |
| FIN-EDGE-06 | Period-close with open GRN Clearing aged into next period | Period 2026-04 closing; GRN G-E6 at doc_status = committed from 2026-04-28 with match flag = unmatched (vendor invoice not received by month-end); Finance Manager runs close. |
Age forward with justification. The unmatched-GRN exception list flags G-E6; Finance Manager records the justification ("invoice expected by 2026-05-10 per vendor SLA"); the period-close gate (Section 3 of 03-user-flow-finance.md) permits the lock with the documented justification; G-E6's GRN Clearing balance ages into the 2026-05 period as opening balance; G-E6 re-appears on the 2026-05 Pending Match worklist; activity log records { action: 'aged_forward', period_from: '2026-04', period_to: '2026-05', gr n: 'G-E6', justification: '...' }. |
saved → committed transition raises the inventory accrual (Dr Inventory / Cr GRN Clearing, GRN_POST_006) that Finance's three-way match clears (Dr GRN Clearing / Cr AP-Trade, GRN_POST_008). Receiver test scenarios live at 04-test-scenarios-receiver.md.GRN_POST_006 (inventory accrual at commit raising the GRN Clearing balance Finance later clears), GRN_POST_007 (three-way-match anchor exposing invoice_no, invoice_date, line net_amount, received_qty for matching), GRN_POST_008 (match success — Dr GRN Clearing / Cr AP-Trade, GRN stays at committed), GRN_POST_009 (match failure — invoice held in dispute, system comment on GRN and PO, no enum transition), GRN_XMOD_007 (Finance / three-way-match cross-module rule), plus GRN_CALC_009–GRN_CALC_011 (three-mode allocation per enum_allocate_extra_cost_type), GRN_CALC_012 (Last Cost feed to costing), GRN_AUTH_007 (Finance pre-AP allocation-edit window), GRN_VAL_005 (invoice-vendor uniqueness), GRN_VAL_010 (is_tax_adjustment override on tax-code edit), GRN_VAL_014 (allocation-complete-at-commit).../carmen-inventory-frontend-e2e/tests/501-grn.spec.ts — canonical Playwright spec for the GRN module. Finance-relevant test groups: TC-GRN-020005 (Filter by Vendor Name and Invoice Number — invoice-side search underpinning Section 2.2 open-GRN lookup), TC-GRN-100001..100003 (Extra Costs — FIN-HP-01..03 allocation-method switching, FIN-VAL-09 manual-sum mismatch), TC-GRN-100002 (No Permission to Add Costs — FIN-PERM-01 boundary), TC-GRN-130001..130004 (Financial Summary — FIN-HP-04 clean match financial breakdown, FIN-HP-05 partial-receipt summary, FIN-VAL-03 invalid-GRN financial view, FIN-HP-07 outdated-calculations / FX recompute), TC-GRN-130002 (Financial Summary — No Permission — FIN-PERM-07 read-scope boundary). Happy-path Finance fixture aligns with the purchase@blueledgers.com test user; permission-denial coverage uses the requestor@blueledgers.com fixture.order_qty and order_unit_price are re-checked at match time to detect upstream drift (Section 2.2 step 3 of 03-user-flow-finance.md).tb_inventory_transaction rows written at GRN commit feed the sub-ledger.tb_inventory_transaction_cost_layer.cost_per_unit via the compensating journal entry per GRN_CALC_012.