diff options
| author | Anders Betts <anders.betts@gmail.com> | 2026-09-19 00:01:25 +0200 |
|---|---|---|
| committer | Anders Betts <anders.betts@gmail.com> | 2026-09-19 00:01:25 +0200 |
| commit | 678d9a58be42c9375511c402642fd621029172c5 (patch) | |
| tree | 6bbaa23c06b92767caf1f188d1f731f4a593054d | |
| parent | 49e44668c14abacef17f0f11be39cbd0faa7ecb9 (diff) | |
| download | bokf-678d9a58be42c9375511c402642fd621029172c5.tar.gz bokf-678d9a58be42c9375511c402642fd621029172c5.zip | |
sru: INK2 report view in the TUI; voucher list tweaksv0.1.31
sru.export now returns the emitted fields as ink2/ink2r/ink2s arrays
plus from/to, so Rapporter -> Inkomstdeklaration (INK2/SRU) renders the
declaration as a table with the official fältnamn before saving; unmapped
accounts are listed in the view.
The voucher list puts the verifikat id before the date, widens the column
gaps and adds an inner margin.
| -rw-r--r-- | clients/bokftui.c | 248 | ||||
| -rw-r--r-- | docs/PROTOCOL.md | 4 | ||||
| -rw-r--r-- | src/sru.c | 27 | ||||
| -rw-r--r-- | tests/test_core.c | 3 |
4 files changed, 278 insertions, 4 deletions
diff --git a/clients/bokftui.c b/clients/bokftui.c index 6c50b1b..33b21de 100644 --- a/clients/bokftui.c +++ b/clients/bokftui.c @@ -2606,8 +2606,8 @@ static void vouchers_screen(struct app *a) snprintf(path, sizeof path, "result.items.%zu.attachment_count", i); int atts = (int)jint_val(resp, path, 0); - snprintf(line, sizeof line, "%c %s %-*s %s", - atts ? 'x' : ' ', date ? date : "", idw, idstr[i], + snprintf(line, sizeof line, " %c %-*s %s %s", + atts ? 'x' : ' ', idw, idstr[i], date ? date : "", desc ? desc : ""); items[i] = xstrdup(line); free(date); @@ -3630,6 +3630,218 @@ static void eskd_save(struct app *a, const char *from, const char *to) free(resp); } +/* Official fältnamn (short) for the INK2/INK2R/INK2S codes; 2025P4. */ +static const struct { + const char *code; + const char *label; +} SRU_LABELS[] = { + { "7011", "Räkenskapsårets början" }, + { "7012", "Räkenskapsårets slut" }, + { "7104", "1.1 Överskott av näringsverksamhet" }, + { "7114", "1.2 Underskott av näringsverksamhet" }, + { "7131", "1.3 Kreditinstituts underlag för riskskatt" }, + { "7132", "1.4 Underlag för särskild löneskatt på pensionskostnader" }, + { "7133", "1.5 Negativt underlag för särskild löneskatt på pensionskostnader" }, + { "7153", "1.6 a Försäkringsföretag m.fl. samt avsatt till pensioner 15 %" }, + { "7154", "1.6 b Utländska pensions- försäkringar 15 %" }, + { "7155", "1.7 a Försäkringsföretag m.fl 30 %" }, + { "7156", "1.7 b Utländska kapitalförsäkringar 30 %" }, + { "80", "1.8 Småhus/ ägarlägenhet" }, + { "93", "1.9 Hyreshus: bostäder" }, + { "84", "1.10 Småhus/ägarlägenhet: tomtmark, byggnad under uppförande" }, + { "86", "1.11 Hyreshus: tomtmark, bostäder under uppförande" }, + { "95", "1.12 Hyreshus: lokaler" }, + { "96", "1.13 Industrienhet och elproduktionsenhet: värme- kraftverk" }, + { "97", "1.14 Elproduktionsenhet, vattenkraftverk" }, + { "98", "1.15 Elproduktionsenhet, vindkraftverk" }, + { "90", "Övriga upplysningar på bilaga" }, + { "1582", "1.16 Förnybar el (kilowattimmar)" }, + { "7011", "Räkenskapsårets början" }, + { "7012", "Räkenskapsårets slut" }, + { "7201", "2.1 Immateriella anläggningstillgångar Koncessioner, patent, licenser, varumärken, hyresrätter, goodwill och liknande rättigheter" }, + { "7202", "2.2 Immateriella anläggningstillgångar Förskott avseende immateriella anläggningstillgångar" }, + { "7214", "2.3 Materiella anläggningstillgångar Byggnader och mark" }, + { "7215", "2.4 Materiella anläggningstillgångar Maskiner, inventarier och övriga materiella anläggningstillgångar" }, + { "7216", "2.5 Materiella anläggningstillgångar Förbättringsutgifter på annans fastighet" }, + { "7217", "2.6 Materiella anläggningstillgångar Pågående nyanläggningar och förskott avseende materiella anläggningstillgångar" }, + { "7230", "2.7 Finansiella anläggningstillgångar Andelar i koncernföretag" }, + { "7231", "2.8 Finansiella anläggningstillgångar Andelar i intresseföretag och gemensamt styrda företag" }, + { "7233", "2.9 Ägarintressen i övriga företag och andra långfristiga värdepappersinnehav" }, + { "7232", "2.10 Finansiella anläggningstillgångar Fordringar hos koncern-, intresse- och gemensamt styrda företag" }, + { "7234", "2.11 Finansiella anläggningstillgångar Lån till delägare eller närstående" }, + { "7235", "2.12 Fordringar hos övriga företag som det finns ett ägarintresse i och andra långfristiga fordringar" }, + { "7241", "2.13 Varulager m.m. Råvaror och förnödenheter" }, + { "7242", "2.14 Varulager Varor under tillverkning" }, + { "7243", "2.15 Varulager Färdiga varor och handelsvaror" }, + { "7244", "2.16 Varulager Övriga lagertillgångar" }, + { "7245", "2.17 Varulager Pågående arbeten för annans räkning" }, + { "7246", "2.18 Varulager Förskott till leverantörer" }, + { "7251", "2.19 Kortfristiga fordringar Kundfordringar" }, + { "7252", "2.20 Kortfristiga fordringar Fordringar hos koncern-, intresse- och gemensamt styrda företag" }, + { "7261", "2.21 Fordringar hos övriga företag som det finns ett ägarintresse i och övriga fordringar" }, + { "7262", "2.22 Kortfristiga fordringar Upparbetad men ej fakturerad intäkt" }, + { "7263", "2.23 Kortfristiga fordringar Förutbetalda kostnader och upplupna intäkter" }, + { "7270", "2.24 Kortfristiga placeringar Andelar i koncernföretag" }, + { "7271", "2.25 Kortfristiga placeringar Övriga kortfristiga placeringar" }, + { "7281", "2.26 Kassa och bank Kassa, bank och redovisningsmedel" }, + { "7301", "2.27 Eget kapital Bundet eget kapital" }, + { "7302", "2.28 Eget kapital Fritt eget kapital" }, + { "7321", "2.29 Obeskattade reserver Periodiseringsfonder" }, + { "7322", "2.30 Obeskattade reserver Ackumulerade överavskrivningar" }, + { "7323", "2.31 Obeskattade reserver Övriga obeskattade reserver" }, + { "7331", "2.32 Avsättningar Avsättningar för pensioner och liknande förpliktelser enligt lag (1967:531)..." }, + { "7332", "2.33 Avsättningar Övriga avsättningar för pensioner och liknande förpliktelser" }, + { "7333", "2.34 Avsättningar Övriga avsättningar" }, + { "7350", "2.35 Långfristiga skulder Obligationslån" }, + { "7351", "2.36 Långfristiga skulder Checkräkningskredit" }, + { "7352", "2.37 Långfristiga skulder Övriga skulder till kreditinstitut" }, + { "7353", "2.38 Långfristiga skulder Skulder till koncern-, intresse- och gemensamt styrda företag" }, + { "7354", "2.39 Skulder till övriga företag som det finns ett ägarintresse i och övriga skulder" }, + { "7360", "2.40 Kortfristiga skulder Checkräkningskredit" }, + { "7361", "2.41 Kortfristiga skulder Övriga skulder till kreditinstitut" }, + { "7362", "2.42 Kortfristiga skulder Förskott från kunder" }, + { "7363", "2.43 Kortfristiga skulder Pågående arbeten för annans räkning" }, + { "7364", "2.44 Kortfristiga skulder Fakturerad men ej upparbetad intäkt" }, + { "7365", "2.45 Kortfristiga skulder Leverantörsskulder" }, + { "7366", "2.46 Kortfristiga skulder Växelskulder" }, + { "7367", "2.47 Kortfristiga skulder Skulder till koncern-, intresse- och gemensamt styrda företag" }, + { "7369", "2.48 Skulder till övriga företag som det finns ett ägarintresse i och övriga skulder" }, + { "7368", "2.49 Kortfristiga skulder Skattesskulder" }, + { "7370", "2.50 Kortfristiga skulder Upplupna kostnader och förutbetalda intäkter" }, + { "7410", "3.1 Nettoomsättning" }, + { "7411", "3.2 Förändring av lager av produkter i arbete, färdiga varor och pågående arbete för annans räkning. +" }, + { "7510", "3.2 Förändring av lager av produkter i arbete, färdiga varor och pågående arbete för annans räkning. -" }, + { "7412", "3.3 Aktiverat arbete för egen räkning" }, + { "7413", "3.4 Övriga rörelseintäkter" }, + { "7511", "3.5 Råvaror och förnödenheter" }, + { "7512", "3.6 Handelsvaror" }, + { "7513", "3.7 Övriga externa kostnader" }, + { "7514", "3.8 Personalkostnader" }, + { "7515", "3.9 Av- och nedskrivningar av materiella och immateriella anläggningstillgångar" }, + { "7516", "3.10 Nedskrivningar av omsättningstillgångar utöver normala nedskrivningar" }, + { "7517", "3.11 Övriga rörelsekostnader" }, + { "7414", "3.12 Resultat från andelar i koncernföretag +" }, + { "7518", "3.12 Resultat från andelar i koncernföretag -" }, + { "7415", "3.13 Resultat från andelar i intresseföretag och gemensamt styrda företag +" }, + { "7519", "3.13 Resultat från andelar i intresseföretag och gemensamt styrda företag -" }, + { "7423", "3.14 Resultat från övriga företag som det finns ett ägarintresse i +" }, + { "7530", "3.14 Resultat från övriga företag som det finns ett ägarintresse i -" }, + { "7416", "3.15 Resultat från övriga finansiella anläggningstillgångar +" }, + { "7520", "3.15 Resultat från övriga finansiella anläggningstillgångar -" }, + { "7417", "3.16 Övriga ränteintäkter och liknande resultatposter" }, + { "7521", "3.17 Nedskrivning av finansiella anläggningstillgångar och kortfristiga placeringar" }, + { "7522", "3.18 Räntekostnader och liknande resultatposter" }, + { "7524", "3.19 Lämnade koncernbidrag" }, + { "7419", "3.20 Mottagna koncernbidrag" }, + { "7420", "3.21 Återföring av periodiseringsfond" }, + { "7525", "3.22 Avsättning till periodiseringsfond" }, + { "7421", "3.23 Förändring av överavskrivningar +" }, + { "7526", "3.23 Förändring av överavskrivningar -" }, + { "7422", "3.24 Övriga bokslutsdispositioner +" }, + { "7527", "3.24 Övriga bokslutsdispositioner -" }, + { "7528", "3.25 Skatt på årets resultat" }, + { "7450", "3.26 Årets resultat, vinst (flyttas till p. 4.1)" }, + { "7550", "3.27 Årets resultat, förlust (flyttas till p. 4.2)" }, + { "7011", "Räkenskapsårets början" }, + { "7012", "Räkenskapsårets slut" }, + { "7650", "4.1 Årets resultat, vinst" }, + { "7750", "4.2 Årets resultat, förlust" }, + { "7651", "4.3a. Bokförda kostnader som inte ska dras av: a. Skatt på årets resultat" }, + { "7652", "b. Bokförda kostnader som inte ska dras av: b. Nedskrivning av finansiella tillgångar" }, + { "7653", "c. Bokförda kostnader som inte ska dras av: c. Andra bokförda kostnader" }, + { "7751", "4.4a. Kostnader som ska dras av men som inte ingår i det redovisade resultatet: a. Lämnade koncernbidrag" }, + { "7764", "b. Kostnader som ska dras av men som inte ingår i det redovisade resultatet: b. Andra ej bokförda kostnader" }, + { "7752", "4.5a. Bokförda intäkter som inte ska tas upp: a. Ackordsvinster" }, + { "7753", "b. Bokförda intäkter som inte ska tas upp: b. Utdelning" }, + { "7754", "c. Bokförda intäkter som inte ska tas upp: c. Andra bokförda intäkter" }, + { "7654", "4.6a. Intäkter som ska tas upp men som inte ingår i det redovisade resultatet a. Beräknad schablonintäkt på periodiseringsfonder vid beskattningsårets ingång" }, + { "7668", "b. Beräknad schablonintäkt på fondandelar ägda vid kalenderårets ingång" }, + { "7655", "c. Intäkter som ska tas upp men som inte ingår i det redovisade resultatet: c. Mottagna koncernbidrag" }, + { "7673", "d. Intäkter som ska tas upp men som inte ingår i det redovisade resultatet: d. Uppräknat belopp vid återföring av periodiseringsfond" }, + { "7665", "e. Intäkter som ska tas upp men som inte ingår i det redovisade resultatet: e. Andra ej bokförda intäkter" }, + { "7755", "4.7a. Avyttring av delägarrätter: a. Bokförd vinst" }, + { "7656", "b. Avyttring av delägarrätter: b. Bokförd förlust" }, + { "7756", "c. Avyttring av delägarrätter: c. Uppskov med kapitalvinst enligt blankett N4" }, + { "7657", "d. Avyttring av delägarrätter: d. Återfört uppskov med kapitalvinst enligt blankett N4" }, + { "7658", "e. Avyttring av delägarrätter: e. Kapitalvinst för beskattningsåret" }, + { "7757", "f. Avyttring av delägarrätter: f. Kapitalförlust som ska dras av" }, + { "7758", "4.8a. Andel i handelsbolag (inkl. avyttring): a. Bokförd intäkt/vinst" }, + { "7659", "b. Andel i handelsbolag (inkl. avyttring): b. Skattemässigt överskott enligt N3B" }, + { "7660", "c. Andel i handelsbolag (inkl. avyttring): c. Bokförd kostnad/förlust" }, + { "7759", "d. Andel i handelsbolag (inkl. avyttring): d. Skattemässigt underskott enligt N3B" }, + { "7666", "4.9 Skattemässig justering av bokfört resultat för avskrivningar på byggnader och annan fast egendom samt restvärdesavskrivning på maskiner och inventarier (+)" }, + { "7765", "4.9 Skattemässig justering av bokfört resultat för avskrivningar på byggnader och annan fast egendom samt restvärdesavskrivning på maskiner och inventarier (-)" }, + { "7661", "4.10 Skattemässig justering av bokfört resultat vid avyttring av näringsfastighet och näringsbostadsrätt" }, + { "7760", "4.10 Skattemässig korrigering av bokfört resultat vid avyttring av näringsfastighet och näringsbostadsrätt: -" }, + { "7761", "4.11 Skogs-/substansminskningsavdrag (specificeras på blankett N8)" }, + { "7662", "4.12 Återföringar vid avyttring av fastighet t.ex. värdeminskningsavdrag, skogsavdrag och substansminskningsavdrag..." }, + { "7663", "4.13 Andra skattemässiga justeringar av resultatet: +" }, + { "7762", "4.13 Andra skattemässiga justeringar av resultatet: -" }, + { "7763", "4.14a. Underskott: a. Outnyttjat underskott från föregående år" }, + { "7671", "4.14b. Reduktion av outnyttjat underskott med hänsyn till beloppsspärr, ackord eller konkurs" }, + { "7672", "4.14c. Reduktion av outnyttjat underskott med hänsyn till koncernbidragsspärr, fusionsspärr m.m. (beloppet ska också tas upp vid p. 1.2. på sid. 1)" }, + { "7670", "4.15 Överskott (flyttas till p. 1.1 på sid. 1)" }, + { "7770", "4.16 Underskott (flyttas till p. 1.2 på sid. 1)" }, + { "8020", "4.17 Årets begärda och tidigare års medgivna värdeminskningsavdrag som finns vid beskattningsårets utgång avseende byggnader." }, + { "8021", "4.18 Årets begärda och tidigare års medgivna värdeminskningsavdrag som finns vid beskattningsårets utgång avseende markanläggningar." }, + { "8023", "4.19 Vid restvärdesavskrivning: återförda belopp för av- och nedskrivning, försäljning, utrangering" }, + { "8026", "4.20 Lån från aktieägare (fysisk person) vid räkenskapsårets utgång" }, + { "8022", "4.21 Pensionskostnader (som ingår i p. 3.8)" }, + { "8028", "4.22 Koncernbidragsspärrat och fusionsspärrat underskott m.m. (frivillig uppgift)" }, + { "8040", "Uppdragstagare (t.ex. redovisningskonsult) har biträtt vid upprättandet av årsredovisningen: Ja" }, + { "8041", "Uppdragstagare (t.ex. redovisningskonsult) har biträtt vid upprättandet av årsredovisningen: Nej" }, + { "8044", "Årsredovisningen har varit föremål för revision: Ja" }, + { "8045", "Årsredovisningen har varit föremål för revision: Nej" }, +}; + +static const char *sru_label(const char *code) +{ + for (size_t i = 0; i < sizeof SRU_LABELS / sizeof SRU_LABELS[0]; i++) + if (strcmp(SRU_LABELS[i].code, code) == 0) + return SRU_LABELS[i].label; + return code; +} + +static void sru_rows(struct buf *t, yyjson_val *arr) +{ + size_t n = yyjson_arr_size(arr); + for (size_t i = 0; i < n; i++) { + yyjson_val *row = yyjson_arr_get(arr, i); + char lbl[256], amt[48]; + pad_label(lbl, sizeof lbl, sru_label(vstr(row, "code")), 66); + kr_format(vint(row, "amount") * 100, amt, sizeof amt); + buf_line(t, "%s %14s\n", lbl, amt); + } +} + +static void fmt_ink2(struct buf *t, const struct app *a, yyjson_val *res) +{ + buf_line(t, "Inkomstdeklaration 2 (INK2)\n%s\n\n", a->org_name); + buf_line(t, "Räkenskapsår: %s - %s\n", vstr(res, "from"), + vstr(res, "to")); + buf_line(t, "Blankett: %s\n", vstr(res, "period")); + buf_line(t, "\nINK2 - huvudblankett\n"); + buf_rule(t, 81); + sru_rows(t, yyjson_obj_get(res, "ink2")); + buf_line(t, "\nINK2R - räkenskapsschema\n"); + buf_rule(t, 81); + sru_rows(t, yyjson_obj_get(res, "ink2r")); + buf_line(t, "\nINK2S - skattemässiga justeringar\n"); + buf_rule(t, 81); + sru_rows(t, yyjson_obj_get(res, "ink2s")); + yyjson_val *un = yyjson_obj_get(res, "unmapped"); + size_t nu = yyjson_arr_size(un); + if (nu) { + buf_line(t, "\nKonton utan SRU-mappning (måste åtgärdas):\n"); + for (size_t i = 0; i < nu; i++) { + yyjson_val *row = yyjson_arr_get(un, i); + char amt[48]; + kr_format(vint(row, "amount_ore"), amt, sizeof amt); + buf_line(t, " %s %s\n", vstr(row, "account"), amt); + } + } +} + static void sru_save(struct app *a) { const char *home = getenv("HOME"); @@ -3708,7 +3920,37 @@ static void reports_screen(struct app *a) if (sel < 0) return; if (sel == 6) { - sru_save(a); + char sargs[64]; + snprintf(sargs, sizeof sargs, "{\"fiscal_year\":%lld}", + (long long)a->fy); + for (;;) { + char *resp = client_rpc(&a->conn, "sru.export", a->session, + a->org, sargs); + if (!resp || !client_ok(resp)) { + show_error("Inkomstdeklaration", resp); + free(resp); + break; + } + yyjson_doc *sd = parse(resp); + yyjson_val *sres = + sd ? jget(yyjson_doc_get_root(sd), "result") : NULL; + struct buf out; + buf_init(&out); + if (sres) + fmt_ink2(&out, a, sres); + else + buf_line(&out, "%s", resp); + buf_append(&out, "", 1); + int sagain = text_view("Rapport", (const char *)out.p, + "s = spara SRU"); + buf_free(&out); + yyjson_doc_free(sd); + free(resp); + if (sagain == 2) + sru_save(a); + if (!sagain) + break; + } continue; } if (sel == 7) { diff --git a/docs/PROTOCOL.md b/docs/PROTOCOL.md index b864d10..20617db 100644 --- a/docs/PROTOCOL.md +++ b/docs/PROTOCOL.md @@ -405,7 +405,9 @@ via the official BAS ranges; INK2S takes the derived årets resultat and skatt plus `adjustments[]{code,amount_ore}` for manual tax adjustments and computes 7670/7770; INK2 carries 7104/7114 and the optional 8040-8045 flags. Non-zero accounts without a mapping abort with `INVALID_ARGS` -unless `ignore_unmapped:true`. +unless `ignore_unmapped:true`. The result also carries `from`/`to` and the +emitted whole-krona fields for display: `ink2[]`, `ink2r[]`, `ink2s[]` with +`{code,amount}`, plus `unmapped[]` when `ignore_unmapped` was used. `report.vat_eskd` builds Skatteverket's `eSKDUpload` Version 6.0 XML for the period ending at `to` (whole kronor, öre truncated @@ -350,6 +350,22 @@ static void date_compact(const char *iso, char out[9]) snprintf(out, 9, "%.4s%.2s%.2s", iso, iso + 5, iso + 8); } +/* The emitted (non-zero) whole-krona fields, in blankett order. */ +static yyjson_mut_val *fields_json(yyjson_mut_doc *doc, const struct fldset *f, + const char *const *order, size_t norder) +{ + yyjson_mut_val *arr = yyjson_mut_arr(doc); + for (size_t i = 0; i < norder; i++) { + int64_t kr = fld_get(f, order[i]) / 100; + if (!kr) + continue; + yyjson_mut_val *o = yyjson_mut_arr_add_obj(doc, arr); + yyjson_mut_obj_add_strcpy(doc, o, "code", order[i]); + yyjson_mut_obj_add_int(doc, o, "amount", kr); + } + return arr; +} + static yyjson_mut_val *file_json(yyjson_mut_doc *doc, const char *fname, const struct buf *b) { @@ -692,6 +708,17 @@ yyjson_mut_val *sru_export(yyjson_mut_doc *doc, sqlite3 *db, int64_t org_id, yyjson_mut_val *o = yyjson_mut_obj(doc); yyjson_mut_obj_add_strcpy(doc, o, "period", type_base); yyjson_mut_obj_add_strcpy(doc, o, "blankett", type_ink2); + yyjson_mut_obj_add_strcpy(doc, o, "from", fy_start); + yyjson_mut_obj_add_strcpy(doc, o, "to", fy_end); + yyjson_mut_obj_add_val(doc, o, "ink2", + fields_json(doc, &ink2, INK2_ORDER, + sizeof INK2_ORDER / sizeof INK2_ORDER[0])); + yyjson_mut_obj_add_val(doc, o, "ink2r", + fields_json(doc, &ink2r, INK2R_ORDER, + sizeof INK2R_ORDER / sizeof INK2R_ORDER[0])); + yyjson_mut_obj_add_val(doc, o, "ink2s", + fields_json(doc, &ink2s, INK2S_ORDER, + sizeof INK2S_ORDER / sizeof INK2S_ORDER[0])); yyjson_mut_obj_add_val(doc, o, "info", info_file); yyjson_mut_obj_add_val(doc, o, "blanketter", blanketter_file); if (unmapped.n > 0) { diff --git a/tests/test_core.c b/tests/test_core.c index bb31fc7..66f8207 100644 --- a/tests/test_core.c +++ b/tests/test_core.c @@ -1618,6 +1618,9 @@ int main(void) CHECK(strstr(sru, "#UPPGIFT 7104 919") != NULL); CHECK(strstr(sru, "#FIL_SLUT") != NULL); free(sru); + CHECK_STR(d, "result.from", "2026-01-01"); + CHECK(find_amount(d, "result.ink2r", "code", "7281", "amount") == 1875); + CHECK(find_amount(d, "result.ink2s", "code", "7670", "amount") == 919); yyjson_doc_free(d); d = call(reqf("{\"v\":1,\"id\":\"126\",\"cmd\":\"sru.export\"," |
