summaryrefslogtreecommitdiff
path: root/clients
diff options
context:
space:
mode:
authorAnders Betts <anders.betts@gmail.com>2026-09-22 22:48:14 +0200
committerAnders Betts <anders.betts@gmail.com>2026-09-22 22:48:14 +0200
commitca267e6b1c727be254c6229fc1ed3e2c5a0d6065 (patch)
tree1182e2d8efa3c0c8f1103e841132230341b83cfa /clients
parentfd08102a4be4e1f26c7afe005842002da923b987 (diff)
downloadbokf-ca267e6b1c727be254c6229fc1ed3e2c5a0d6065.tar.gz
bokf-ca267e6b1c727be254c6229fc1ed3e2c5a0d6065.zip
sru, tui: round every account to whole kronor; fix the årsredovisning Stäng skipv0.1.67
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'clients')
-rw-r--r--clients/screens_bokslut.c92
-rw-r--r--clients/screens_reports.c2
2 files changed, 56 insertions, 38 deletions
diff --git a/clients/screens_bokslut.c b/clients/screens_bokslut.c
index 96c6fe9..a4776c9 100644
--- a/clients/screens_bokslut.c
+++ b/clients/screens_bokslut.c
@@ -311,13 +311,17 @@ struct ar_year {
char label[8];
char from[16], to[16];
int64_t netto, ror, res_fin, skatt, res, disp;
+ int64_t res_exact;
int64_t fin_in, fin_out;
int64_t groups[AR_GROUPS];
};
/* Balance-sheet amounts are shown the way an annual report reads them:
- credit balances (equity, liabilities) as positive numbers. */
-static int64_t ar_bs_ib_sum(yyjson_val *res, int lo, int hi)
+ credit balances (equity, liabilities) as positive numbers. Each account
+ is rounded to whole kronor before it is summed (util_round_kr), so every
+ line and total adds up; exact keeps öre for the rounding balance. */
+static int64_t ar_bs_total(yyjson_val *res, int lo, int hi, const char *field,
+ int exact)
{
int64_t s = 0;
if (!res)
@@ -330,37 +334,45 @@ static int64_t ar_bs_ib_sum(yyjson_val *res, int lo, int hi)
yyjson_val *row = yyjson_arr_get(arr, i);
if (!acct_in(vstr(row, "account"), lo, hi))
continue;
- int64_t ib = vint(row, "ib_ore");
- s += lo >= 2000 ? -ib : ib;
+ int64_t v = vint(row, field);
+ if (lo >= 2000)
+ v = -v;
+ s += exact ? v : util_round_kr(v);
}
}
return s;
}
+static int64_t ar_bs_ib_sum(yyjson_val *res, int lo, int hi)
+{
+ return ar_bs_total(res, lo, hi, "ib_ore", 0);
+}
+
static int64_t ar_bs_sum(yyjson_val *res, int lo, int hi)
{
- int64_t s = 0;
- if (!res)
- return 0;
- for (int k = 0; k < 3; k++) {
- yyjson_val *sec = yyjson_obj_get(res, BS_KEYS[k]);
- yyjson_val *arr = sec ? yyjson_obj_get(sec, "accounts") : NULL;
- size_t n = yyjson_arr_size(arr);
- for (size_t i = 0; i < n; i++) {
- yyjson_val *row = yyjson_arr_get(arr, i);
- if (!acct_in(vstr(row, "account"), lo, hi))
- continue;
- int64_t ub = vint(row, "ub_ore");
- s += lo >= 2000 ? -ub : ub;
- }
- }
- return s;
+ return ar_bs_total(res, lo, hi, "ub_ore", 0);
+}
+
+/* The krona that rounding leaves between the balance sheet's two sides, to
+ be carried by Balanserat resultat. 2099 is left out: Årets resultat is
+ the income statement's figure. A real imbalance stays visible. */
+static int64_t ar_bs_rounding(yyjson_val *res, const char *field,
+ int64_t result_kr, int64_t result_exact)
+{
+ int64_t a_kr = ar_bs_total(res, 1000, 1999, field, 0);
+ int64_t a_ex = ar_bs_total(res, 1000, 1999, field, 1);
+ int64_t el_kr = ar_bs_total(res, 2000, 2098, field, 0) +
+ ar_bs_total(res, 2100, 2999, field, 0) + result_kr;
+ int64_t el_ex = ar_bs_total(res, 2000, 2098, field, 1) +
+ ar_bs_total(res, 2100, 2999, field, 1) + result_exact;
+ return (a_kr - el_kr) - util_round_kr(a_ex - el_ex);
}
-/* One year's income statement from its general ledger. Vouchers whose
- description starts with "Stäng" are the source system's closings in
- imported history years and are skipped, so those years show their real
- figures instead of a zeroed P&L. */
+/* One year's income statement from its general ledger. SIE-imported
+ vouchers whose description starts with "Stäng" are the source system's
+ closings and are skipped (the same rule as report.income_statement), so
+ those years show their real figures instead of a zeroed P&L. Each account
+ is rounded to whole kronor before it is summed. */
static void ar_load_year(struct ar_year *y, yyjson_val *gl)
{
memset(y, 0, sizeof *y);
@@ -381,15 +393,18 @@ static void ar_load_year(struct ar_year *y, yyjson_val *gl)
size_t nr = yyjson_arr_size(rows);
for (size_t k = 0; k < nr; k++) {
yyjson_val *row = yyjson_arr_get(rows, k);
- if (strncmp(vstr(row, "description"), "Stäng", 7) == 0)
+ if (strcmp(vstr(row, "source"), "sie_import") == 0 &&
+ strncmp(vstr(row, "description"), "Stäng",
+ strlen("Stäng")) == 0)
continue;
net += vint(row, "debit_ore") - vint(row, "credit_ore");
}
- int64_t disp = -net;
+ int64_t disp = util_round_kr(-net);
int done = 0;
for (size_t g = 0; g < AR_GROUPS; g++) {
if (acct_in(num, IS_GROUPS[g].lo, IS_GROUPS[g].hi)) {
y->groups[g] += disp;
+ y->res_exact -= net;
done = 1;
break;
}
@@ -404,6 +419,9 @@ static void ar_load_year(struct ar_year *y, yyjson_val *gl)
y->disp += disp;
else if (n >= 8900 && n <= 8989)
y->skatt += disp;
+ else
+ continue;
+ y->res_exact -= net;
}
int64_t rev = 0, cost = 0;
for (size_t g = 0; g < AR_GROUPS; g++)
@@ -590,8 +608,11 @@ static void fmt_arsredovisning(struct buf *t, const struct app *a,
int64_t ak_ib = ar_bs_ib_sum(bs, 2081, 2089);
int64_t ak_ub = ar_bs_sum(bs, 2081, 2089);
- int64_t br_ib = ar_bs_ib_sum(bs, 2091, 2098);
- int64_t br_ub = ar_bs_sum(bs, 2091, 2098);
+ int64_t br_ib = ar_bs_ib_sum(bs, 2091, 2098) +
+ ar_bs_rounding(bs, "ib_ore", prev_ars,
+ prev ? prev->res_exact : 0);
+ int64_t br_ub = ar_bs_sum(bs, 2091, 2098) +
+ ar_bs_rounding(bs, "ub_ore", ars, cur->res_exact);
int64_t movement = br_ub - br_ib;
int64_t paid_div = prev_ars - movement;
if (paid_div < 0)
@@ -749,13 +770,10 @@ static void fmt_arsredovisning(struct buf *t, const struct app *a,
buf_line(t, MK_HEAD "Fritt eget kapital\n");
ar_row(t, "Balanserat resultat", br_ub, br_ib, 1);
ar_row(t, "Årets resultat", ars, prev_ars, 1);
- ar_row(t, "Summa fritt eget kapital", ar_bs_sum(bs, 2091, 2098) + ars,
- ar_bs_ib_sum(bs, 2091, 2098) + prev_ars, 1);
- ar_row(t, "Summa eget kapital",
- ar_bs_sum(bs, 2000, 2090) + ar_bs_sum(bs, 2091, 2098) + ars,
- ar_bs_ib_sum(bs, 2000, 2090) + ar_bs_ib_sum(bs, 2091, 2098) +
- prev_ars,
- 0);
+ ar_row(t, "Summa fritt eget kapital", br_ub + ars, br_ib + prev_ars, 1);
+ int64_t eq_ub = ar_bs_sum(bs, 2000, 2090) + br_ub + ars;
+ int64_t eq_ib = ar_bs_ib_sum(bs, 2000, 2090) + br_ib + prev_ars;
+ ar_row(t, "Summa eget kapital", eq_ub, eq_ib, 0);
buf_line(t, "\n");
ar_row(t, "Obeskattade reserver", ar_bs_sum(bs, 2100, 2199),
ar_bs_ib_sum(bs, 2100, 2199), 0);
@@ -775,8 +793,8 @@ static void fmt_arsredovisning(struct buf *t, const struct app *a,
int64_t skuld_p = ar_bs_ib_sum(bs, 2400, 2999);
ar_row(t, "Summa kortfristiga skulder", skuld, skuld_p, 1);
ar_row(t, "Summa eget kapital, avsättningar och skulder",
- ar_bs_sum(bs, 2000, 2999) + ars,
- ar_bs_ib_sum(bs, 2000, 2999) + prev_ars, 0);
+ eq_ub + ar_bs_sum(bs, 2100, 2999),
+ eq_ib + ar_bs_ib_sum(bs, 2100, 2999), 0);
buf_line(t, "\n" MK_HEAD "Noter\n\nNot 1 Redovisnings- och"
" värderingsprinciper\n");
diff --git a/clients/screens_reports.c b/clients/screens_reports.c
index e6263a2..a06e914 100644
--- a/clients/screens_reports.c
+++ b/clients/screens_reports.c
@@ -819,7 +819,7 @@ static const struct {
{ "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" },
+ { "7368", "2.49 Kortfristiga skulder Skatteskulder" },
{ "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. +" },