From 6de6ffa3e52a2bec519c2a052d0f26d01e38f167 Mon Sep 17 00:00:00 2001 From: Anders Betts Date: Fri, 18 Sep 2026 09:50:29 +0200 Subject: bokftui: IB view shows effective opening balances, edits post deltas to them Was listing the IB voucher's rows (the reconciliation deltas) and computing edits against those, which mismatched reports on years with carry-forward and could not set a target balance. Also guard the editor against more than 63 rows. --- clients/bokftui.c | 76 ++++++++++++++++++------------------------------------- 1 file changed, 25 insertions(+), 51 deletions(-) (limited to 'clients') diff --git a/clients/bokftui.c b/clients/bokftui.c index 15ca335..5daa606 100644 --- a/clients/bokftui.c +++ b/clients/bokftui.c @@ -3171,6 +3171,8 @@ static void ibrow_normalize(struct tui_ibrow *rows, int *nrows, int *field) } /* Loads the net IB per account for the active fiscal year. */ +/* Effective opening balances of the selected year: the year's IB vouchers + plus all earlier movements, exactly what the reports show. */ static int ib_load(struct app *a, char ***out_acc, int64_t **out_amt, int *out_n) { @@ -3178,67 +3180,33 @@ static int ib_load(struct app *a, char ***out_acc, int64_t **out_amt, *out_amt = NULL; *out_n = 0; char args[128]; - snprintf(args, sizeof args, "{\"fiscal_year\":%lld,\"series\":\"IB\"," - "\"limit\":200}", + snprintf(args, sizeof args, + "{\"fiscal_year\":%lld,\"include_zero\":true}", (long long)a->fy); - char *resp = - client_rpc(&a->conn, "voucher.list", a->session, a->org, args); + char *resp = client_rpc(&a->conn, "report.trial_balance", a->session, + a->org, args); if (!resp || !client_ok(resp)) { show_error("Ingående balans", resp); free(resp); return -1; } - size_t n = jarr_size(resp, "result.items"); - size_t cap = n ? n : 1; - char **accs = xcalloc(cap, sizeof(char *)); - int64_t *amts = xcalloc(cap, sizeof(int64_t)); + size_t n = jarr_size(resp, "result.accounts"); + char **accs = xcalloc(n ? n : 1, sizeof(char *)); + int64_t *amts = xcalloc(n ? n : 1, sizeof(int64_t)); int count = 0; for (size_t i = 0; i < n; i++) { char path[64]; - snprintf(path, sizeof path, "result.items.%zu.id", i); - int64_t id = jint_val(resp, path, 0); - if (id <= 0) + snprintf(path, sizeof path, "result.accounts.%zu.ib_ore", i); + int64_t ib = jint_val(resp, path, 0); + if (ib == 0) continue; - char vargs[64]; - snprintf(vargs, sizeof vargs, "{\"id\":%lld}", (long long)id); - char *v = client_rpc(&a->conn, "voucher.get", a->session, a->org, vargs); - if (!v || !client_ok(v)) { - free(v); + snprintf(path, sizeof path, "result.accounts.%zu.account", i); + char *acc = jstr_dup(resp, path); + if (!acc) continue; - } - size_t rn = jarr_size(v, "result.rows"); - for (size_t k = 0; k < rn; k++) { - char p[64]; - snprintf(p, sizeof p, "result.rows.%zu.account", k); - char *acc = jstr_dup(v, p); - snprintf(p, sizeof p, "result.rows.%zu.debit_ore", k); - int64_t d = jint_val(v, p, 0); - snprintf(p, sizeof p, "result.rows.%zu.credit_ore", k); - int64_t c = jint_val(v, p, 0); - if (acc) { - int found = -1; - for (int j = 0; j < count; j++) - if (strcmp(accs[j], acc) == 0) { - found = j; - break; - } - if (found >= 0) { - amts[found] += d - c; - } else { - if ((size_t)count == cap) { - cap *= 2; - accs = xrealloc(accs, cap * sizeof(char *)); - amts = xrealloc(amts, cap * sizeof(int64_t)); - } - accs[count] = acc; - amts[count] = d - c; - count++; - } - if (found >= 0) - free(acc); - } - } - free(v); + accs[count] = acc; + amts[count] = ib; + count++; } free(resp); *out_acc = accs; @@ -3259,6 +3227,11 @@ static int64_t ib_old_lookup(char **accs, int64_t *amts, int n, static int ib_form(struct app *a, char **old_acc, int64_t *old_amt, int nold) { static struct tui_ibrow rows[64]; + if (nold > 63) { + message("Ingående balans", + "För många konton (%d) för att redigera här.", nold); + return 0; + } memset(rows, 0, sizeof rows); for (int i = 0; i < nold && i < 63; i++) { snprintf(rows[i].account, sizeof rows[i].account, "%s", old_acc[i]); @@ -3565,7 +3538,8 @@ static void ib_screen(struct app *a) top = 0; frame("Ingående balans"); attron(A_BOLD); - mvprintw(2, 2, "Räkenskapsår %s serie IB", a->fy_label); + mvprintw(2, 2, "Räkenskapsår %s ingående balans (effektiv)", + a->fy_label); mvaddstr(4, 2, "Konto"); mvaddstr(4, 9, "Namn"); mvaddstr(4, 62, "Belopp"); -- cgit v1.3