feat(bookkeeping): Ny verifikat modal, ledger-style list, SIE no-underlag exemptions (#698)
* feat(bookkeeping): Ny verifikat modal, ledger-style list, SIE no-underlag exemptions Verifikat UX - "Ny verifikat" opens in a modal (NewJournalEntryDialog) instead of an inline tab; the review step renders inline in the dialog rather than stacking a second dialog. - JournalEntryForm: konteringsrader are the focus, with a compact pre-filled metadata bar (datum/serie/text/valuta/period) on top; verifikationstext auto-fills from the first row's account. - JournalEntryList: belopp shown on collapsed rows; expanded view is an aligned Konto/Benämning/Debet/Kredit table. SIE imports no longer flood "Att hantera: saknade underlag" - Import gains an opt-in (off by default) toggle to mark imported verifikat as "Inget underlag krävs"; a "Rekommenderas vid migrering" badge nudges it for historical years. - Multi-select batch-mark in the list for selective cleanup. - Filter-scoped bulk mark (POST /api/bookkeeping/no-doc-required/bulk-missing): marks every missing-doc verifikat matching the active filters across all pages, with a dry_run count to confirm scope — the scalable remedy for a post-import flood. - Shared helper markEntriesNoDocRequired + per-entry batch route. Tests: no-doc helper, batch route, bulk-missing route. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(bookkeeping): address PR #698 review findings - JournalEntryForm: restore the explicit "no underlag" acknowledgement in the modal's inline review. When no document is attached, the confirm button reads "Bokför utan underlag" (BFL 5 kap 6-7 §§), equivalent to the blocking dialog the non-bare flow shows — the bare path no longer posts behind only a passive banner. - batch no-doc route: guard the ownership query with source_type IN NEEDS_DOC_SOURCE_TYPES so a crafted request can't exempt non-document-requiring entries (defense in depth on top of company + posted scoping). - bulk-missing route: resolve doc/exemption status by querying only the candidate ids (chunked) instead of loading the company's full document_attachments and journal_entry_no_doc_required tables into memory — data minimisation + bounded memory for large migrations (the most-repeated reviewer finding). Triaged as non-issues (left as-is): partial-import exemption (gated on result.success == zero errors), reason write-back (sidecar row is FK-linked and carries the reason), and "bulk-exempting manual entries" (consistent with the existing per-entry NoDocRequiredToggle). No DB migration — reuses the existing journal_entry_no_doc_required table. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(bookkeeping): centralize bulk-missing date/series validation in Zod Move the ISO-date and verifikationsserie format checks into the Zod schema so malformed input is rejected with a clean 400 instead of being silently nulled (or, for a shaped-but-invalid date, throwing a 500 via fetchAllRows). The date refinement rejects values like 9999-99-99 / 2026-02-30 that a bare /^\d{4}-\d{2}-\d{2}$/ regex lets through. Addresses the PR #698 reviewer nit on split schema-vs-runtime validation. +2 route tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
64991eb3c9
commit
4dfd790de5
+21
-1
@@ -2908,7 +2908,24 @@
|
||||
"no_doc_required_suggestion_interest": "Interest",
|
||||
"no_doc_required_suggestion_internal_transfer": "Internal transfer",
|
||||
"no_doc_required_suggestion_tax_payment": "Tax payment",
|
||||
"no_doc_required_suggestion_salary": "Salary"
|
||||
"no_doc_required_suggestion_salary": "Salary",
|
||||
"account_column": "Account",
|
||||
"description_column": "Description",
|
||||
"sum_label": "Total",
|
||||
"batch_select_all": "Select all ({count})",
|
||||
"batch_select_row": "Select entry",
|
||||
"batch_selected_count": "{count} selected",
|
||||
"batch_mark_no_doc": "Mark as no document required",
|
||||
"batch_clear_selection": "Clear",
|
||||
"batch_no_doc_done_title": "Marked as no document required",
|
||||
"batch_no_doc_done_description": "{count} entries updated.",
|
||||
"batch_mark_all_missing": "Mark all without documents",
|
||||
"bulk_mark_title": "Mark all without documents",
|
||||
"bulk_mark_counting": "Counting entries...",
|
||||
"bulk_mark_none": "No entries without documents match the filter.",
|
||||
"bulk_mark_body": "{count} entries without a supporting document match the current filter. They will be marked \"No supporting document required\". You can undo this per entry afterwards.",
|
||||
"bulk_mark_confirm": "Mark {count}",
|
||||
"bulk_cancel": "Cancel"
|
||||
},
|
||||
"attachment_preview_sheet": {
|
||||
"title": "Attachments",
|
||||
@@ -3098,6 +3115,8 @@
|
||||
"review_title": "Review journal entry",
|
||||
"review_title_with_voucher": "Review journal entry ({voucher})",
|
||||
"review_warning": "A journal entry is created and cannot be edited afterwards. Corrections are made via storno.",
|
||||
"review_back": "Back",
|
||||
"review_confirm": "Create entry",
|
||||
"no_doc_dialog_title": "Document missing",
|
||||
"no_doc_dialog_warning": "No document attached. Under the Swedish Accounting Act (BFL 5 kap. 6-7 §§) every accounting entry must have a verification as supporting document. You can attach one now or continue without.",
|
||||
"no_doc_confirm": "Post without document",
|
||||
@@ -3431,6 +3450,7 @@
|
||||
"tab_journal": "Journal entries",
|
||||
"tab_new_entry": "New journal entry",
|
||||
"tab_accounts": "Chart of accounts",
|
||||
"new_entry_dialog_title": "New journal entry",
|
||||
"loading_source_voucher": "Loading source voucher...",
|
||||
"copy_failed_title": "Could not copy journal entry",
|
||||
"copy_source_missing": "Source voucher not found.",
|
||||
|
||||
+21
-1
@@ -2908,7 +2908,24 @@
|
||||
"no_doc_required_suggestion_interest": "Ränta",
|
||||
"no_doc_required_suggestion_internal_transfer": "Intern överföring",
|
||||
"no_doc_required_suggestion_tax_payment": "Skatteinbetalning",
|
||||
"no_doc_required_suggestion_salary": "Lön"
|
||||
"no_doc_required_suggestion_salary": "Lön",
|
||||
"account_column": "Konto",
|
||||
"description_column": "Benämning",
|
||||
"sum_label": "Summa",
|
||||
"batch_select_all": "Markera alla ({count})",
|
||||
"batch_select_row": "Markera verifikat",
|
||||
"batch_selected_count": "{count} markerade",
|
||||
"batch_mark_no_doc": "Markera som inget underlag krävs",
|
||||
"batch_clear_selection": "Avmarkera",
|
||||
"batch_no_doc_done_title": "Markerade som inget underlag krävs",
|
||||
"batch_no_doc_done_description": "{count} verifikat uppdaterade.",
|
||||
"batch_mark_all_missing": "Markera alla utan underlag",
|
||||
"bulk_mark_title": "Markera alla utan underlag",
|
||||
"bulk_mark_counting": "Räknar verifikat...",
|
||||
"bulk_mark_none": "Inga verifikat utan underlag matchar filtret.",
|
||||
"bulk_mark_body": "{count} verifikat som saknar underlag matchar nuvarande filter. De markeras som \"Inget underlag krävs\". Du kan ångra per verifikat efteråt.",
|
||||
"bulk_mark_confirm": "Markera {count}",
|
||||
"bulk_cancel": "Avbryt"
|
||||
},
|
||||
"attachment_preview_sheet": {
|
||||
"title": "Bilagor",
|
||||
@@ -3098,6 +3115,8 @@
|
||||
"review_title": "Granska verifikation",
|
||||
"review_title_with_voucher": "Granska verifikation ({voucher})",
|
||||
"review_warning": "En verifikation skapas och kan inte ändras efteråt. Korrigeringar görs genom storno.",
|
||||
"review_back": "Tillbaka",
|
||||
"review_confirm": "Skapa verifikat",
|
||||
"no_doc_dialog_title": "Underlag saknas",
|
||||
"no_doc_dialog_warning": "Inget underlag bifogat. Enligt bokföringslagen (BFL 5 kap. 6-7 §§) ska varje bokföringspost ha en verifikation som underlag. Du kan bifoga underlag nu eller fortsätta utan.",
|
||||
"no_doc_confirm": "Bokför utan underlag",
|
||||
@@ -3431,6 +3450,7 @@
|
||||
"tab_journal": "Verifikationer",
|
||||
"tab_new_entry": "Ny verifikation",
|
||||
"tab_accounts": "Kontoplan",
|
||||
"new_entry_dialog_title": "Ny verifikation",
|
||||
"loading_source_voucher": "Laddar källverifikat...",
|
||||
"copy_failed_title": "Kunde inte kopiera verifikat",
|
||||
"copy_source_missing": "Källverifikatet hittades inte.",
|
||||
|
||||
Reference in New Issue
Block a user