fix(orders): book webshop orders against 1686 and stop the missing-account dead end (#1697)
Booking an order from the Orders page could fail outright on a fresh company. seed_chart_of_accounts() seeds a deliberately small chart: 3001/3002/3003 and 2611/2621/2631 are in it, but 3004, 3740 and the clearing account are not. All three are reachable from an entirely ordinary order (a 0%-rate line, an ore residual, or simply no payment-method mapping yet), and the engine treats a missing or inactive account as AccountsNotInChartError, so the user's first click on Bokfor returned an error naming accounts they had no reason to know about, with no way forward but to hand-add them. The book route now ensures the closed set of accounts our own prefill can emit exists before drafting. Deliberately narrow: only accounts in WEBSHOP_PREFILL_ACCOUNTS are ever created, and only when a submitted line uses one, so an account the user typed still surfaces as a real error instead of quietly growing the chart. A deactivated row is reactivated rather than duplicated, and every failure is swallowed so the engine's typed error still wins over a chart tidy-up. The unmapped default also moves from 1680 to 1686. 1680 is the generic "Andra kortfristiga fordringar" parent; 1686 "Fordringar for kontokort och kuponger" is what BAS defines for a claim on a payment provider, which is what money sitting at Klarna or Stripe actually is. The Stripe extension already settles against 1686, so a store running both surfaces now shares one clearing account instead of splitting the same receivable across two. 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
Jakob Wennberg
Claude Fable 5
parent
3a1b842e4a
commit
bb5fafe87b
@@ -1043,6 +1043,7 @@ One line per decision: `[YYYY-MM-DD] <decision>: <why>`. Appended by agents and
|
||||
[2026-08-17] Supplier standardkonto empty-string fix lives in the API schemas, split by verb: '' normalizes to undefined on create (key dropped, column NULL) but to null on update, because update routes pass validated fields straight into .update() where undefined means "leave unchanged"; without the null mapping a cleared standardkonto/e-post would silently never clear. Client keeps sending '' as-is (the old email-strip hack removed), since stripping client-side would break exactly that clear path. The field itself became an AccountCombobox filtered to cost classes 4-7 (matches the agent-path expenseAccountField rule); other 4-digit numbers stay typeable, and the API still enforces format only. Standardkonto stays optional: it only prefills supplier-invoice lines, and the ledger-context suggestion covers the empty case, so requiring it (what the bug accidentally did) is wrong for the target user.
|
||||
[2026-08-17] Replay-masking skeptic round (PR #1639): explicit data-ph tags now resolve BEFORE the th chrome fallback in replayMaskText (a single closest over tags-plus-th let a th nested in a masked container win on DOM proximity, CodeRabbit); seven missed text-leak sites got call-site masks (delete-invoice number, credit-page number, IB voucher ref, TIC orgnr since TIC serves it unnormalized so the separator scrub cannot be relied on, articles search term, dimension segment labels, activate-account buttons); the attribute channel (placeholders prefilled with effective values, title tooltips) is handled with rrweb's blockClass: user-data placeholders carry ph-no-capture, which removes the element from the recording while app UX keeps the founder-approved prefill-override pattern intact. Chose ph-no-capture over stripping the placeholders because the prefilled effective value IS the UX.
|
||||
[2026-08-17] Skattekontoutdrag file import (Sebastian's request) writes into skattekonto_transactions, not into transactions as a pseudo-bank with 1630 unlocked in BankFileConfirmStep: rows inherit the skattekonto_rules 1630 booking engine, matching, drift and both UIs for free, while the literal ask would bypass the rules and double against the SKV inbox for connected companies. Dedup pairs file hash-keys with API id-keys by CONTENT in both directions (import-time skip/promote against existing rows, sync-time takeover that rewrites an imported row's key in place so journal links survive connecting the API later). Import is free for everyone per the requireSkvCapability doctrine (manual paths never blocked); only sync/saldo stay capability-gated. The parse route hard-rejects files that fail detectSkattekontoFile and statements whose opening+sum!=closing, and warns on orgnr mismatch against company_settings: wrong-company imports are a known support-incident class.
|
||||
[2026-08-18] Webshop order booking defaults to BAS 1686 (Fordringar för kontokort och kuponger), not 1680: 1680 is the generic "Andra kortfristiga fordringar" parent, while 1686 is the account BAS defines for a claim on a payment provider (bas.se moved this receivable off 1580 onto 1686 for exactly that reason), and the Stripe extension already settles against 1686, so a store running both surfaces now shares one clearing account. Separately, booking a webshop order no longer dies on AccountsNotInChartError: seed_chart_of_accounts() seeds a minimal chart that omits 3004, 3740 and any clearing account, all of which an ordinary order reaches (0%-rate line, öre residual, unmapped payment method), so the book route now ensures the closed WEBSHOP_PREFILL_ACCOUNTS set exists first. Deliberately narrow and non-fatal: only accounts our own prefill emits are ever auto-created (a user-typed account still errors), a deactivated row is reactivated rather than duplicated, and any failure is swallowed so the engine's typed error still wins. Inserts go one literal-payload row at a time because the no-phantom-columns guard cannot resolve a .map()-built array, and verifying the 13 columns beats saving at most eight first-use round trips.
|
||||
[2026-08-17] articles.housework_type keeps two vocabularies (Skatteverket arbetstypskod, or bare ROT/RUT) instead of migrating legacy ROT/RUT rows: a kind-only row cannot be upgraded to a code without knowing the work, so the article form preserves the legacy choice as an explicit option and the invoice prefill treats it as kind-only; everything else normalizes to null and is rejected at the API.
|
||||
[2026-08-17] ROT/RUT claim completeness (arbetstyp + arbetstimmar) is enforced at invoice creation (validateInvoice + CreateInvoiceItemSchema + editor), not only at begäran-file time: the file blocker fired when the invoice was already numbered/booked/paid with no repair path short of a credit note; schablontjänster (TRANSPORT/TVATT) stay hours-exempt. Yearly ceiling accumulation is per CUSTOMER in the editor (personnummer is ciphertext client-side) and warning-only; server warnings are still dropped on success, so the editor computes its own via the shared deductionCapWarnings helper.
|
||||
[2026-08-17] invoices.remaining_amount gets a BEFORE INSERT trigger deriving total - paid_amount - deduction_total when a fresh unpaid real invoice arrives with NULL/0, instead of only fixing the writers: four writers had drifted (proforma conversion x2, MCP create_invoice, sandbox seed) and 337 open invoices on prod sat at 0, so the column's DEFAULT 0 must never be able to mean 'settled' again; UPDATE is left to the settlement code, which legitimately writes 0 on full payment. Writers fixed too (defense in depth).
|
||||
|
||||
Reference in New Issue
Block a user