feat(expenses): expense claims module (utlägg) (#2145)

Contributed by @joakimhew. Maintainer commits on top: migration re-versioned to 20260904170000 (main's 20260901210000 took the original version), payout batches booked atomically through the create_expense_payout_batch RPC, accounted-api skill regenerated, main merged. Closes #2143.
This commit is contained in:
Joakim Hansson
2026-09-05 13:36:51 +02:00
committed by GitHub
parent f7f40c04e4
commit 397a3b9bca
24 changed files with 5085 additions and 5 deletions
+116
View File
@@ -8061,6 +8061,122 @@
"payment_shortfall_label": "Missing on the account",
"pgnote": "Synced automatically every night. Completed events are booked against 1630 Skattekonto, usually automatically, and deviations are flagged here. Kronofogden: {amount}."
},
"expense_claims": {
"title": "Expense claims",
"description": "Purchases you or an employee paid privately. Registering books the cost against a liability account; the payout clears the liability.",
"new_claim": "New expense claim",
"new_claim_help": "The claim is booked immediately as a verifikat: cost and VAT against the liability account (2893 for owners, 2820 for employees).",
"viewer_disabled_tooltip": "You have read-only access in this company",
"outstanding_to": "Owed to {name}:",
"filter_all": "All statuses",
"status_registered": "Registered",
"status_paid": "Paid out",
"empty_title": "No expense claims yet",
"empty_description": "Register receipts that you or employees paid privately, and reimburse them in batches whenever it suits.",
"th_date": "Date",
"th_description": "Description",
"th_claimant": "Person",
"th_receipt": "Receipt",
"th_status": "Status",
"th_amount": "Amount",
"select_claim": "Select claim for payout",
"select_all_claims": "Select all",
"outstanding_select_hint": "Click to select this person's claims",
"payouts_heading": "Booked payouts",
"payout_cash_account": "Cash account",
"payout_view_entry": "Entry",
"receipt_attached": "Attached",
"receipt_missing": "Missing",
"created": "Expense claim registered and booked",
"create_failed": "Could not register the expense claim",
"payout_created": "Payout booked",
"payout_failed": "Could not create the payout",
"payout_selection_invalid": "A payout can only cover one person with the same liability account",
"payout_action": "Pay out {count, plural, one {# claim} other {# claims}} · {total}",
"payout_title": "Pay out expense claims",
"payout_help": "{count, plural, =1 {One claim} other {# claims}} to {name}, {total} in total. One verifikat is booked: the liability account is debited and the cash account credited. Make the actual bank transfer for the same amount.",
"payout_date": "Payout date",
"payout_account": "Cash account",
"payout_confirm": "Book payout",
"form_description": "Description",
"form_description_placeholder": "e.g. USB hub, Kjell & Company",
"form_date": "Expense date",
"form_claimant": "Person",
"form_claimant_owner": "Owner ({account})",
"form_owner_name": "Name",
"owner_fallback_name": "Owner",
"form_amount": "Amount incl. VAT",
"form_vat": "Of which VAT",
"form_currency": "Currency",
"form_fx_hint": "Amounts are entered in the selected currency and converted to SEK at the Riksbank rate for the expense date.",
"form_expense_account": "Expense account",
"form_receipt": "Receipt from the inbox",
"form_pick_from_inbox": "Pick from inbox",
"form_receipt_upload": "Drop or pick a receipt",
"form_receipt_none": "No receipt",
"form_receipt_warning": "A receipt is required as accounting records (BFL). Register now, but attach the receipt as soon as possible.",
"form_cancel": "Cancel",
"form_register": "Register & book",
"step_details": "Step 1 · Receipt & details",
"step_booking": "Step 2 · Booking",
"step_booking_help": "Review the full verifikat before it is booked. Search the expense account by number or name.",
"dropzone_hint": "Drag and drop or click",
"dropzone_ai_hint": "AI reads the receipt",
"upload_uploading": "Uploading…",
"upload_extracting": "AI is reading the receipt…",
"upload_extracted": "AI-extracted, fields prefilled",
"upload_no_extraction": "Uploaded (no extraction)",
"upload_remove": "Remove the receipt",
"upload_failed": "The upload failed",
"form_back": "Back",
"form_next": "Next: review the verifikat",
"preview_account": "Account",
"form_seller_country": "Seller's country",
"template_search_placeholder": "Search templates …",
"book_manually": "Book manually",
"book_manually_help": "Pick the account and country yourself, or edit the rows freely.",
"no_templates_found": "No templates match the search.",
"show_receipt": "Show receipt",
"hide_receipt": "Hide receipt",
"templates_recommended": "Recommended",
"templates_ai_badge": "AI suggestions",
"templates_ai_loading": "AI is suggesting templates from the description …",
"templates_recent": "Recently used",
"templates_all": "All templates",
"seller_country_se": "Sweden",
"seller_country_eu": "From an EU country",
"seller_country_noneu": "From outside the EU",
"seller_country_abroad": "Abroad",
"rc_region_label": "Inside or outside the EU?",
"rc_region_placeholder": "Select region",
"rc_region_required": "Choose whether the seller is inside or outside the EU: the choice decides whether the basis lands in box 21 or box 22.",
"seller_country_eu_hint": "Reverse charge: the cost stays on the cost account, the box 21 base is booked as a 4535/4598 pair and calculated VAT as 2614/2645. The VAT field from step 1 is not used.",
"seller_country_noneu_hint": "Reverse charge: the cost stays on the cost account, the box 22 base is booked as a 4531/4598 pair and calculated VAT as 2614/2645. The VAT field from step 1 is not used.",
"seller_country_gross_hint": "Foreign VAT is not deductible: the full amount including local VAT is booked as cost. Applies to e.g. hotels, restaurants and taxis, taxed where performed.",
"rc_toggle": "Reverse charge (goods and main-rule services, e.g. SaaS)",
"load_failed": "The expense claims could not be loaded.",
"load_retry": "Try again",
"template_applied": "Template: {name}",
"clear_template": "Remove template",
"edit_rows": "Edit rows",
"hide_row_editor": "Hide row editor",
"save_as_template": "Save as template",
"add_row": "Add row",
"remove_row": "Remove row",
"balanced": "Debit = Credit",
"unbalanced": "Unbalanced",
"preview_debit": "Debit",
"preview_credit": "Credit",
"preview_summary": "Booked {date} as an expense claim for {name}. The receipt is attached to the verifikat.",
"preview_fx_note": "Amounts are converted to SEK at the Riksbank rate for the expense date when booked.",
"payout_account_placeholder": "Pick an account",
"row_delete": "Remove",
"delete_title": "Remove expense claim",
"delete_help": "\"{description}\" ({total}) is removed from the list and its verifikat is cancelled with a reversal entry (storno). The receipt stays in the archive.",
"delete_confirm": "Remove & reverse",
"deleted": "Expense claim removed and the verifikat reversed",
"delete_failed": "Could not remove the expense claim"
},
"mileage": {
"title": "Driving log",
"new_trip": "New trip",
+116
View File
@@ -8061,6 +8061,122 @@
"payment_shortfall_label": "Saknas på kontot",
"pgnote": "Synkas automatiskt varje natt. Genomförda händelser bokförs mot 1630 Skattekonto, oftast automatiskt, och avvikelser flaggas här. Kronofogden: {amount}."
},
"expense_claims": {
"title": "Utlägg",
"description": "Köp du eller en anställd betalat privat. Registrering bokför kostnaden mot ett skuldkonto; utbetalningen nollar skulden.",
"new_claim": "Nytt utlägg",
"new_claim_help": "Utlägget bokförs direkt som verifikat: kostnad och moms mot skuldkontot (2893 för ägare, 2820 för anställda).",
"viewer_disabled_tooltip": "Du har endast läsbehörighet i detta företag",
"outstanding_to": "Att betala till {name}:",
"filter_all": "Alla statusar",
"status_registered": "Registrerat",
"status_paid": "Utbetalt",
"empty_title": "Inga utlägg ännu",
"empty_description": "Registrera kvitton som du eller anställda betalat privat, och betala ut dem i klump när det passar.",
"th_date": "Datum",
"th_description": "Beskrivning",
"th_claimant": "Person",
"th_receipt": "Underlag",
"th_status": "Status",
"th_amount": "Belopp",
"select_claim": "Välj utlägg för utbetalning",
"select_all_claims": "Markera alla",
"outstanding_select_hint": "Klicka för att markera personens utlägg",
"payouts_heading": "Bokförda utbetalningar",
"payout_cash_account": "Likvidkonto",
"payout_view_entry": "Verifikat",
"receipt_attached": "Bifogat",
"receipt_missing": "Saknas",
"created": "Utlägg registrerat och bokfört",
"create_failed": "Kunde inte registrera utlägget",
"payout_created": "Utbetalning bokförd",
"payout_failed": "Kunde inte skapa utbetalningen",
"payout_selection_invalid": "En utbetalning kan bara avse en person med samma skuldkonto",
"payout_action": "Betala ut {count} utlägg · {total}",
"payout_title": "Betala ut utlägg",
"payout_help": "{count, plural, =1 {Ett utlägg} other {# utlägg}} till {name}, totalt {total}. Ett verifikat bokförs: skuldkontot debiteras och likvidkontot krediteras. Gör själva banköverföringen med samma belopp.",
"payout_date": "Utbetalningsdatum",
"payout_account": "Likvidkonto",
"payout_confirm": "Bokför utbetalning",
"form_description": "Beskrivning",
"form_description_placeholder": "t.ex. USB-hubb, Kjell & Company",
"form_date": "Utläggsdatum",
"form_claimant": "Person",
"form_claimant_owner": "Ägare ({account})",
"form_owner_name": "Namn",
"owner_fallback_name": "Ägare",
"form_amount": "Belopp inkl. moms",
"form_vat": "Varav moms",
"form_currency": "Valuta",
"form_fx_hint": "Beloppen anges i vald valuta och räknas om till SEK med Riksbankens kurs för utläggsdatumet.",
"form_expense_account": "Kostnadskonto",
"form_receipt": "Underlag från inkorgen",
"form_pick_from_inbox": "Välj från inkorgen",
"form_receipt_upload": "Släpp eller välj kvitto",
"form_receipt_none": "Inget underlag",
"form_receipt_warning": "Kvitto krävs som räkenskapsinformation (BFL). Registrera gärna, men komplettera med underlag så snart som möjligt.",
"form_cancel": "Avbryt",
"form_register": "Registrera & bokför",
"step_details": "Steg 1 · Kvitto & detaljer",
"step_booking": "Steg 2 · Bokföring",
"step_booking_help": "Granska hela verifikatet innan det bokförs. Sök kostnadskonto på nummer eller namn.",
"dropzone_hint": "Dra och släpp eller klicka",
"dropzone_ai_hint": "AI läser kvittot",
"upload_uploading": "Laddar upp…",
"upload_extracting": "AI tolkar kvittot…",
"upload_extracted": "AI-tolkat, fälten ifyllda",
"upload_no_extraction": "Uppladdat (ingen tolkning)",
"upload_remove": "Ta bort kvittot",
"upload_failed": "Uppladdningen misslyckades",
"form_back": "Tillbaka",
"form_next": "Nästa: granska verifikatet",
"preview_account": "Konto",
"form_seller_country": "Säljarens land",
"template_search_placeholder": "Sök mall …",
"book_manually": "Bokför manuellt",
"book_manually_help": "Välj konto och land själv, eller redigera raderna fritt.",
"no_templates_found": "Inga mallar matchar sökningen.",
"show_receipt": "Visa kvitto",
"hide_receipt": "Dölj kvitto",
"templates_recommended": "Rekommenderade",
"templates_ai_badge": "AI-förslag",
"templates_ai_loading": "AI föreslår mallar utifrån beskrivningen …",
"templates_recent": "Senast använda",
"templates_all": "Alla mallar",
"seller_country_se": "Sverige",
"seller_country_eu": "Från EU-land",
"seller_country_noneu": "Från icke EU-land",
"seller_country_abroad": "Utomlands",
"rc_region_label": "Inom eller utanför EU?",
"rc_region_placeholder": "Välj region",
"rc_region_required": "Välj om säljaren finns inom eller utanför EU: valet avgör om underlaget hamnar i ruta 21 eller ruta 22.",
"seller_country_eu_hint": "Omvänd moms: kostnaden ligger kvar på kostnadskontot, ruta 21-underlaget bokförs som 4535/4598-par och beräknad moms som 2614/2645. Momsfältet från steg 1 används inte.",
"seller_country_noneu_hint": "Omvänd moms: kostnaden ligger kvar på kostnadskontot, ruta 22-underlaget bokförs som 4531/4598-par och beräknad moms som 2614/2645. Momsfältet från steg 1 används inte.",
"seller_country_gross_hint": "Utländsk moms är inte avdragsgill: hela beloppet inklusive lokal moms bokförs som kostnad. Gäller t.ex. hotell, restaurang och taxi som beskattas där de utförs.",
"rc_toggle": "Omvänd skattskyldighet (varor och tjänster enligt huvudregeln, t.ex. SaaS)",
"load_failed": "Utläggen kunde inte hämtas.",
"load_retry": "Försök igen",
"template_applied": "Mall: {name}",
"clear_template": "Ta bort mallen",
"edit_rows": "Redigera rader",
"hide_row_editor": "Dölj radredigering",
"save_as_template": "Spara som mall",
"add_row": "Lägg till rad",
"remove_row": "Ta bort rad",
"balanced": "Debet = Kredit",
"unbalanced": "Obalanserad",
"preview_debit": "Debet",
"preview_credit": "Kredit",
"preview_summary": "Bokförs {date} som utlägg för {name}. Kvittot kopplas till verifikatet.",
"preview_fx_note": "Beloppen räknas om till SEK med Riksbankens kurs för utläggsdatumet vid bokföring.",
"payout_account_placeholder": "Välj konto",
"row_delete": "Ta bort",
"delete_title": "Ta bort utlägg",
"delete_help": "\"{description}\" ({total}) tas bort ur listan och verifikatet annulleras med en ändringsverifikation (storno). Kvittot ligger kvar i arkivet.",
"delete_confirm": "Ta bort & annullera",
"deleted": "Utlägget borttaget och verifikatet annullerat",
"delete_failed": "Kunde inte ta bort utlägget"
},
"mileage": {
"title": "Körjournal",
"new_trip": "Ny resa",