fix(documents): anchor floating supplier-invoice underlag instead of nagging (#1248)
A verifikat booked from a supplier invoice showed the invoice PDF when opened while the list kept warning "Underlag saknas" on the same row. Both surfaces behaved as written: every missing-underlag surface only accepts a referenced supplier-invoice document when it is ANCHORED to a journal entry (only anchored docs sit behind block_document_deletion), while the verifikat view's reference resolver displayed the document regardless. The document was floating because delete_last_voucher clears journal_entry_id on everything attached to the voucher it tears down (the FK is ON DELETE RESTRICT, so it must). Deleting a rättelse the invoice PDF had been relinked onto therefore orphaned it while the payment verifikat stayed posted, and nothing ever anchored it again: the warning was unresolvable by design. Same class one surface over: v1 mark-paid never linked the document at all, dashboard mark-paid only did so for the cash entry, and both match-supplier-invoice routes propagated the transaction's document but not the invoice's own. Four of the five affected prod rows come from those paths, not from a deleted voucher. - lib/core/documents/supplier-invoice-underlag.ts: anchor a floating document to the invoice's own posted verifikat (registration, then payment, then partial payments; open unlocked periods only). Never moves an anchored doc, never throws. - Called after delete_last_voucher and from all four payment paths. - getJournalEntryUnderlagReferences withholds an unanchored document so the verifikat view and the warning can no longer contradict each other. - Migration 20260727180000 backfills the rows already in this state. Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
771dfd45ba
commit
69c537fd1f
@@ -620,3 +620,4 @@ One line per decision: `[YYYY-MM-DD] <decision>: <why>`. Appended by agents and
|
||||
[2026-07-27] performSync keeps `provider` optional, defaulting to Google Drive: it preserves the pre-Dropbox call shape (and its test suite) as the documented legacy path while all three production call sites pass a provider explicitly.
|
||||
[2026-07-27] Privacy page corrected after verifying prod: PostHog's conversations module writes ph_conv_<token> = {"widgetSessionId": uuid} to localStorage at PAGE LOAD, not when support is contacted, bypassing persistence: 'memory' exactly like surveys' seenSurvey_ flags. The page previously claimed enkäter were the only local storage, which was wrong the moment Support was enabled. Both values are functional UI state without personuppgifter (do-not-ask-again, and find-my-own-ticket), so the no-consent-banner position holds, but "inga kakor eller annan lagring" did not and is now stated accurately. Worth remembering that enabling any new PostHog product can silently add device storage: check localStorage in prod after each one rather than trusting the persistence setting.
|
||||
[2026-07-27] Documented the two client-side storage keys as having DIFFERENT lifecycles, after the compliance swarm flagged ISO 27001 A.8.10 (no deletion mechanism) on the storage inventory. ph_conv_<token> IS deleted on logout: posthog.reset() calls the conversations manager's own reset, which removes that single known key, and resetAnalyticsIdentity() already runs in both logout handlers. That is what stops a shared device carrying one user's support-ticket session into the next user's session. seenSurvey_<id> genuinely has no deletion trigger, and cannot have one from the SDK: no PostHog bundle enumerates localStorage (zero occurrences of localStorage.key( or Object.keys(localStorage) across module.js, surveys.js, conversations.js), so nothing can discover the keys to remove them. Accepted as the retention position rather than an oversight: the value is "true" under an opaque survey id with no personal data, and clearing it on logout would re-prompt every survey to the next person on the device and produce false survey responses.
|
||||
[2026-07-27] Fixed the "Underlag saknas on a verifikat that shows the invoice" contradiction by ANCHORING the floating document, not by loosening the missing-underlag predicate. The predicate's anchoring requirement (migration 20260724090000) is legally right: block_document_deletion keys on journal_entry_id, so an unanchored doc is deletable and must not silence the warning. The bug was that nothing ever anchored it, and delete_last_voucher actively un-anchors (it must: the FK is ON DELETE RESTRICT). So the fix re-anchors after a voucher delete, at every supplier-invoice payment path (dashboard + v1 mark-paid, dashboard + v1 match-supplier-invoice, which between them had zero, partial and cash-only coverage), and backfills the 5 prod rows. getJournalEntryUnderlagReferences now also withholds an unanchored document, so the verifikat view and the list can no longer state opposite things about the same row. Rejected the alternative (extend the WORM deletion guard to protect docs referenced by a supplier invoice, then drop the anchoring requirement everywhere): it touches an enforcement trigger for a strictly larger blast radius and leaves the document outside the guard until the trigger ships.
|
||||
|
||||
Reference in New Issue
Block a user