fix(vat,documents): EU reverse-charge packs feed ruta 20/21; daily reanchor cron for floating supplier-invoice underlag (#2095)

Two user reports (Anders, 2026-08-25 + 2026-08-29):

1. The seeded standardmallar "Inkop EU-varor/-tjanster, omvand moms 25%"
   booked the cost on 4010/6540, which no momsdeklaration ruta reads, so the
   fiktiv moms filled ruta 30/48 while ruta 20/21 (inkopsvarde) stayed 0;
   Skatteverket rejects that (FK004, ML 13 kap). The packs now book directly
   on the basis accounts 4515/4535 (ACCOUNT_RUTA -> ruta 20/21); the
   transaction-picker path already skips its own basis emission for basis
   debit accounts, so no double counting. Regression test pins every
   reverse-charge pack to a 44xx/45xx business debit. Prod rows update via
   the existing pack sync cron (upsert on pack_slug).

2. A kontantmetod payment verifikat stayed "Underlag saknas" although the
   invoice PDF was attached and eligible on every static condition: the
   inline anchorSupplierInvoiceDocument silently did nothing (prod case
   2026-08-28, verified in audit_log: no document_attachments update between
   the payment booking and the user's manual re-upload). The helper now
   verifies the guarded update actually matched a row instead of claiming
   success on zero rows, logs its silent bail branches, and a new daily cron
   (/api/documents/reanchor/cron) re-runs the anchor for any floating
   retained document with a posted verifikat, replacing the pattern of
   one-off repair migrations (20260727180000, 20260824150000). The sweep
   names the FK in its embed and is idempotent; locked/closed periods are
   skipped as before.


Claude-Session: https://claude.ai/code/session_01Jj6Rg1ViyFRej55gbxLVgj

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Mattsson
2026-09-01 10:16:07 +02:00
committed by GitHub
co-authored by Claude Fable 5
parent 08dbfdc5c4
commit e113e9c099
12 changed files with 376 additions and 10 deletions
+1
View File
@@ -32,6 +32,7 @@
45 3 * * * curl -sf -H "Authorization: Bearer ${CRON_SECRET}" ${APP_URL}/api/extensions/woocommerce/orders/cron
15 3 * * * curl -sf -H "Authorization: Bearer ${CRON_SECRET}" ${APP_URL}/api/extensions/shopify/orders/cron
0 3 * * * curl -sf -H "Authorization: Bearer ${CRON_SECRET}" ${APP_URL}/api/documents/verify/cron
30 3 * * * curl -sf -H "Authorization: Bearer ${CRON_SECRET}" ${APP_URL}/api/documents/reanchor/cron
0 4 * * * curl -sf -H "Authorization: Bearer ${CRON_SECRET}" ${APP_URL}/api/sandbox/cleanup/cron
0 2 * * * curl -sf -H "Authorization: Bearer ${CRON_SECRET}" ${APP_URL}/api/events/cleanup/cron
0 * * * * curl -sf -H "Authorization: Bearer ${CRON_SECRET}" ${APP_URL}/api/extensions/cloud-backup/auto-sync/cron
+1
View File
@@ -32,6 +32,7 @@
45 3 * * * curl -sf -H "Authorization: Bearer ${CRON_SECRET}" ${APP_URL}/api/extensions/woocommerce/orders/cron
15 3 * * * curl -sf -H "Authorization: Bearer ${CRON_SECRET}" ${APP_URL}/api/extensions/shopify/orders/cron
0 3 * * * curl -sf -H "Authorization: Bearer ${CRON_SECRET}" ${APP_URL}/api/documents/verify/cron
30 3 * * * curl -sf -H "Authorization: Bearer ${CRON_SECRET}" ${APP_URL}/api/documents/reanchor/cron
0 4 * * * curl -sf -H "Authorization: Bearer ${CRON_SECRET}" ${APP_URL}/api/sandbox/cleanup/cron
0 2 * * * curl -sf -H "Authorization: Bearer ${CRON_SECRET}" ${APP_URL}/api/events/cleanup/cron
0 * * * * curl -sf -H "Authorization: Bearer ${CRON_SECRET}" ${APP_URL}/api/extensions/cloud-backup/auto-sync/cron