fix(salary): show the AGI kvittensnummer from agi_declarations regardless of who fetched it (#1692)
* fix(salary): show the AGI kvittensnummer from agi_declarations regardless of who fetched it
When the kvittens cron (or the post-connect refresh) picks up a signed AGI it
deletes the period-scoped agi_submission_{period} cache on purpose, and the
salary run then rendered "Skickad till Skatteverket <date>" with no
kvittensnummer, signatory or signing time even though all three were stored
on agi_declarations. Since the cron runs every 15 minutes while the panel
polls only three times after the signing link is created, that was the
normal outcome for anyone who signs at an unhurried pace (#1597).
GET /agi/status now serves the receipt from agi_declarations
(kvittensnummer, response_data.signeradAv/signeradTid, submitted_at,
submittedAtEstimated) whenever the cache is absent; the cache still wins
when present because it is the only place the in-flight states live. The
declaration-sourced record deliberately carries no salaryRunId (the period
row is repointed at a correction run on regeneration), so ownership is
resolved from signeradTid/submittedAt against the run's agi_submitted_at
stamp and from updatedAt = submitted_at. AGIPanel labels the timestamp as
approximate when it is our reconciliation-time fallback rather than
Skatteverket's signeradTid. The MCP gnubok_agi_status tool uses the same
read.
Closes #1597
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* ci: retry stalled Vercel preview build
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
Jakob Wennberg
parent
7d56e0ec01
commit
83932f2e07
@@ -1061,3 +1061,4 @@ One line per decision: `[YYYY-MM-DD] <decision>: <why>`. Appended by agents and
|
||||
[2026-08-18] IBAN prefill reads only enabled, still-connected SEK cash_accounts: disconnect keeps rows (bank_connection_id nulled) and the connect picker mirrors deselected accounts, so an unfiltered read could offer a closed or third-party IBAN as invoice payee (skeptic refutation on PR #1695).
|
||||
[2026-08-18] Editor PDF preview (#1686) recomputes ROT/RUT server-side from the posted lines with the same helpers as build-invoice-write.ts (computeDeduction / computeInvoiceDeductionTotal, base inkl. moms at the rendered rate, invoice-doc only) and resolves the masked personnummer the same way (typed value, else an individual customer's kundkort personnummer): the client is not trusted with the deduction math, and the preview must state the same avdrag row, info box and "Att betala" as the invoice that gets created. The editor now also posts deduction_personnummer / deduction_housing_designation to the preview route, only when a line claims a deduction (same privacy rule as buildInvoiceWritePayload). Swish QR amount in the preview follows buildSwishQrDataUrl, fixed separately in #1685.
|
||||
[2026-08-18] Skatteverket read data is visible to every company member, no new role gate (#1673): token rows are per (user, company) but the fetched skattekonto/declaration data belongs to the company, and viewers already read `skattekonto_transactions` and the local snapshot with no role check; membership (dispatcher-resolved ctx.companyId + company-scoped SELECT policy on `skatteverket_tokens`) is the gate. Reads resolve the caller's own token first, then the most recently issued active token of any member (all rows ordered, never `.maybeSingle()`, which errored once two members had connected). Writes (moms utkast/las/submit, AGI submit/spara/las, connect/disconnect, /status) stay on the caller's own token: BankID signing is personal.
|
||||
[2026-08-18] AGI receipt fallback (#1597): GET /agi/status serves the signed record from agi_declarations (kvittensnummer, response_data.signeradAv/signeradTid, submitted_at) only when the agi_submission_{period} cache is absent, and the declaration-sourced record deliberately carries NO salaryRunId: the period row is UNIQUE per company+period and regenerating a correction repoints its salary_run_id at the correction run while the stored kvittens still belongs to the original, so trusting the column would render the correction as filed with a superseded receipt. Ownership rests on signeradTid/submittedAt vs the run's agi_submitted_at stamp (same value) plus updatedAt = submitted_at, which predates any later correction's XML. Cache present still wins because it is the only place the in-flight states live. Rejected: a second client fetch in AGIPanel (two sources of truth for one card) and merging both records in the route (mixes another declaration's fields into an in-flight state).
|
||||
|
||||
Reference in New Issue
Block a user