fix(bookkeeping): classify template audit evidence (#1594)
This commit is contained in:
@@ -48,11 +48,13 @@ anything.
|
||||
`gnubok_correct_entry`. Never `gnubok_reverse_journal_entry` alone: the
|
||||
business event remains valid, only its classification is wrong.
|
||||
- Do not write directly to `journal_entries` or `journal_entry_lines`.
|
||||
- Any `effective_lock_status` other than `open` is a hard stop. The correction
|
||||
path never bypasses a lock. Unlocking or reopening requires a separately
|
||||
reviewed and explicitly approved workflow for the exact company and period.
|
||||
If a declaration or closing has relied on the period, establish the required
|
||||
omprövning or closing consequences before requesting that approval.
|
||||
- Any `effective_lock_status` other than `open` is a hard stop for the current
|
||||
`gnubok_correct_entry` path. Never unlock, reopen or edit the original merely
|
||||
to make a correction possible. A locked-period correction requires a
|
||||
separately reviewed and tested path that records a storno and replacement in
|
||||
an open period, references the original, and preserves who corrected it and
|
||||
when. If a declaration or closing relied on the locked period, establish the
|
||||
required omprövning or closing consequences before requesting approval.
|
||||
- Never run a production correction without explicit approval for the exact
|
||||
company, vouchers and replacement lines.
|
||||
- No automated bulk mutation. Ever.
|
||||
@@ -63,16 +65,41 @@ Run [`scripts/audit-template-misbookings.sql`](../scripts/audit-template-misbook
|
||||
against the intended database. It is read-only, creates nothing, and returns
|
||||
only posted entries.
|
||||
|
||||
**Output is diagnostic, never a verdict.** There is no provenance link from a
|
||||
posted entry back to the template that produced it (`template_id` lives on
|
||||
`mapping_rules`, not on journal entries), so candidates are matched by account
|
||||
signature, and both signatures have legitimate shapes:
|
||||
The audit now separates the broad signature from the evidence classification.
|
||||
There is no direct template id on a journal entry, but `source_type`, exact line
|
||||
shape, transaction context and linked underlag can rule candidates in or out.
|
||||
Both signatures still have legitimate shapes:
|
||||
|
||||
- `5820` is the **correct** account for actual car hire.
|
||||
- Representation at 25% is lawful only when the supply is actually subject to
|
||||
25% VAT and the supplier invoice is correct.
|
||||
|
||||
Read `review_priority` as an ordering aid only:
|
||||
Read `evidence_classification` as the remediation queue:
|
||||
|
||||
| Classification | Meaning |
|
||||
|---|---|
|
||||
| `confirmed_correction` | Exact defective shape plus corroborating evidence. Review the underlag, then stage `gnubok_correct_entry` and request explicit approval for the exact voucher and replacement lines. |
|
||||
| `insufficient_evidence` | The shape matches, but the underlag or provenance is not decisive. Obtain evidence before proposing any write. |
|
||||
| `false_positive` | Not attributable to either defective live template. This is not a general verdict that every aspect of the voucher is correct. |
|
||||
|
||||
`source_type` values `import` and `correction` are false positives for this
|
||||
template-remediation audit because neither live template generated them. Keep
|
||||
any independent accounting concern outside this remediation batch.
|
||||
|
||||
Linked underlag is resolved from direct journal-entry and journal-line links,
|
||||
transactions and supplier invoices. Document identifiers and extracted VAT
|
||||
signals are returned, but storage paths and file names are not. A decisive 25%
|
||||
extraction on a representation voucher rules out the defective 12% restaurant
|
||||
template signature. It does not by itself prove that the representation cap,
|
||||
participant record or business purpose was handled correctly.
|
||||
|
||||
Every representation row therefore carries
|
||||
`independent_representation_review = participants_purpose_and_300_sek_vat_base_cap_required`.
|
||||
`observed_6072_cost_exceeds_300_sek` is a triage signal only: the statutory cap
|
||||
is per person and occasion, so the number of participants and the underlag are
|
||||
still required.
|
||||
|
||||
Read `review_priority` as a supporting ordering aid:
|
||||
|
||||
| Priority | Meaning |
|
||||
|---|---|
|
||||
@@ -82,14 +109,25 @@ Read `review_priority` as an ordering aid only:
|
||||
| `manual_review_5820_no_corroborating_signal` | A `5820` entry with no hotel-shaped text or 12% VAT ratio. Most likely legitimate car hire. |
|
||||
| `manual_review_6072_with_vat` | A `6072` entry with `2641` VAT whose aggregate ratio is not exactly 25%. It may be correct or may be a mixed voucher masking the defective representation leg. |
|
||||
|
||||
The classifier is verified against read-only probes: a hotel booked to `5820`
|
||||
ranks high, a genuine car hire on `5820` falls to manual review, and an exact
|
||||
25% representation signature ranks high. Correct 12% representation and mixed
|
||||
vouchers whose aggregate ratio is not 25% remain visible for manual review,
|
||||
because unrelated `2641` lines can otherwise hide a defective representation
|
||||
component. The representation probes include multiple `6072` and `2641` lines;
|
||||
the audit aggregates them per entry and returns one candidate instead of a
|
||||
many-to-many set of line pairs.
|
||||
The classifier is verified against read-only probes for confirmed, insufficient
|
||||
and false-positive outcomes. The audit aggregates multiple `6072` and `2641`
|
||||
lines per entry and returns one candidate instead of a many-to-many set of line
|
||||
pairs. Mixed representation vouchers without decisive underlag remain
|
||||
`insufficient_evidence`; they are never cleared merely because their aggregate
|
||||
VAT ratio differs from the exact defective 25% signature.
|
||||
|
||||
Treat lock and VAT-return impact as overlays, not evidence classes:
|
||||
|
||||
- `effective_lock_status` identifies candidates that the current correction
|
||||
service cannot handle. Never unlock or reopen merely to permit a correction.
|
||||
- `vat_return_impact = potential_if_confirmed` means a representation candidate
|
||||
could affect ruta 48. Determine the filing status before requesting approval.
|
||||
- `vat_reporting_period`, `vat_deadline_statuses` and `vat_filing_status`
|
||||
surface the in-app filing record. `not_proven_by_in_app_records` is unknown,
|
||||
not proof that no declaration was filed externally.
|
||||
- Keep exact company and voucher identifiers in an access-controlled approval
|
||||
manifest. Public issue updates should use aggregate batches unless disclosure
|
||||
has been explicitly approved.
|
||||
|
||||
## Review each candidate
|
||||
|
||||
@@ -107,8 +145,8 @@ many-to-many set of line pairs.
|
||||
filed. If so, an omprövning is in scope and the ledger correction alone is
|
||||
not sufficient.
|
||||
6. Decide materiality. A 40 kr VAT difference on one lunch two years ago in a
|
||||
closed period is unlikely to warrant reopening anything; a systematic error
|
||||
across a year is different. Record the decision either way.
|
||||
closed period may not warrant a separate correction in an open period; a
|
||||
systematic error across a year is different. Record the decision either way.
|
||||
|
||||
Keep the reviewed set, the evidence, the proposed replacement lines and the
|
||||
reviewer identity together as the correction record.
|
||||
@@ -121,6 +159,12 @@ retain `original_lines`, copy every original line, change only what is wrong,
|
||||
verify the replacement balances, stage
|
||||
`gnubok_correct_entry`, and approve only with explicit authorisation.
|
||||
|
||||
`gnubok_correct_entry` routes through `correctEntry()` in
|
||||
`lib/core/bookkeeping/storno-service.ts`. It retains the original, creates a
|
||||
posted storno with `reverses_id`, creates the replacement with
|
||||
`correction_of_id`, and records the acting user and timestamps. Never replace
|
||||
this audited envelope with direct journal-table writes.
|
||||
|
||||
For the hotel defect, the only change is `account_number` on the cost line,
|
||||
`5820` to `5830`.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user