diff options
| -rw-r--r-- | clients/bokftui.c | 76 | ||||
| -rw-r--r-- | docs/PROTOCOL.md | 7 | ||||
| -rw-r--r-- | docs/STATE.md | 6 |
3 files changed, 33 insertions, 56 deletions
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"); diff --git a/docs/PROTOCOL.md b/docs/PROTOCOL.md index 009b14e..f282691 100644 --- a/docs/PROTOCOL.md +++ b/docs/PROTOCOL.md @@ -404,9 +404,10 @@ commands. Implemented screens (0.1.0-dev): - **Nytt verifikat** — row editor with live balance display, F5 dry-run validation and F9 posting; one `client_ref` per form makes retries safe. F4 applies a konteringsmall (prompts for template and `x`). -- **Ingående balans** — the series `IB` voucher for the selected fiscal year; - enter accounts with signed amounts (positive debit, negative credit), the - editor posts deltas so existing entries are never edited. +- **Ingående balans** — the effective opening balances of the selected + fiscal year (carry-forward plus any `IB` vouchers, as the reports compute + them); enter accounts with signed amounts (positive debit, negative + credit); the editor posts `IB` deltas so nothing is ever edited. - **Välj organisation att representera** — login step two: pick which org the session works in. `--org ID` skips the picker for scripts. - **Byt räkenskapsår** (dashboard) — pick from the org's fiscal years; shown diff --git a/docs/STATE.md b/docs/STATE.md index f130f14..3cbe448 100644 --- a/docs/STATE.md +++ b/docs/STATE.md @@ -41,8 +41,10 @@ server/protocol/ledger only. instead of delete. 9. **Ingående balans**: one series `IB` voucher per fiscal year (dated at year start). Reports treat series IB as IB, not period movement; SIE - export/import round-trips without double counting; TUI editor posts only - deltas so nothing is ever edited. + export/import round-trips without double counting; TUI editor shows the + year's *effective* opening balances (carry-forward plus IB vouchers) and + posts deltas, so nothing is ever edited and a target balance can be + entered directly. 10. **Attachments**: content stored in the DB (BLOB), immutable, linked via append-only `voucher_attachments`. Default limit 10 MiB (`max_attachment_bytes`); the socket line limit is derived from it |
