diff options
Diffstat (limited to 'clients/screens_accounts.c')
| -rw-r--r-- | clients/screens_accounts.c | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/clients/screens_accounts.c b/clients/screens_accounts.c new file mode 100644 index 0000000..d6640f9 --- /dev/null +++ b/clients/screens_accounts.c @@ -0,0 +1,173 @@ +#include <dirent.h> +#include <errno.h> +#include <locale.h> +#include <math.h> +#include <ncursesw/ncurses.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <time.h> +#include <unistd.h> + +#include "client.h" +#include "tui.h" +#include "formula.h" +#include "util.h" +#include "version.h" +#include "yyjson.h" +#include "ui.h" + +static const char *type_sv(const char *t) +{ + if (!t) + return ""; + if (strcmp(t, "asset") == 0) + return "Tillgång"; + if (strcmp(t, "liability") == 0) + return "Skuld"; + if (strcmp(t, "equity") == 0) + return "Eget kapital"; + if (strcmp(t, "revenue") == 0) + return "Intäkt"; + if (strcmp(t, "expense") == 0) + return "Kostnad"; + return t; +} + +/* Moms treatment for an account: the stored vat_code when set, otherwise + derived from the BAS account name (which carries the rate). Accounts + whose treatment depends on the transaction stay blank. */ +static const char *vat_display(const char *name, const char *vat_code, + char *buf, size_t cap) +{ + if (vat_code && *vat_code) { + snprintf(buf, cap, "%s", vat_code); + return buf; + } + if (!name || !*name) + return ""; + int pct = 0; + for (const char *p = name; *p;) { + if (*p >= '0' && *p <= '9') { + const char *q = p; + int v = 0; + while (*q >= '0' && *q <= '9') { + v = v * 10 + (*q - '0'); + q++; + } + while (*q == ' ') + q++; + if (*q == '%') { + pct = v; + break; + } + p = q; + continue; + } + p++; + } + int in = strstr(name, "Ingående moms") != NULL; + int out = strstr(name, "Utgående moms") != NULL; + int reverse = strstr(name, "omvänd") != NULL; + if (in || out) { + if (pct) + snprintf(buf, cap, "%s %d%%", in ? "Ing" : "Utg", pct); + else + snprintf(buf, cap, "%s", in ? "Ing" : "Utg"); + return buf; + } + if (pct) { + snprintf(buf, cap, "%d%%%s", pct, reverse ? " omv" : ""); + return buf; + } + if (strstr(name, "momsfri") || strstr(name, "momsfritt") || + strstr(name, "momsefri")) + return "Momsfri"; + if (strstr(name, "Redovisningskonto för moms")) + return "Avräkning"; + if (reverse) + return "Omvänd"; + if (strstr(name, "moms")) + return "Moms"; + return ""; +} + +/* Kontolista: every account with the details that apply to it. */ +void accounts_report(struct app *a) +{ + for (;;) { + char *resp = client_rpc(&a->conn, "account.list", a->session, a->org, + "{\"active_only\":false}"); + if (!resp || !client_ok(resp)) { + show_error("Kontolista", resp); + free(resp); + return; + } + size_t n = jarr_size(resp, "result.items"); + int name_w = COLS - 45; + if (name_w < 12) + name_w = 12; + struct buf text; + buf_init(&text); + char line[2048]; + int hdr = snprintf(line, sizeof line, + MK_STICKY "%-6s %-*s %-12s %-5s %-6s %-8s\n", + "Konto", name_w, "Namn", "Typ", "Aktiv", "SRU", + "Moms"); + buf_append(&text, line, (size_t)hdr); + int sep_w = 6 + 1 + name_w + 1 + 12 + 1 + 5 + 1 + 6 + 1 + 8; + for (int i = 0; i < sep_w && i < (int)sizeof line - 1; i++) + line[i] = '-'; + line[sep_w < (int)sizeof line ? sep_w : (int)sizeof line - 1] = '\n'; + buf_append(&text, line, (size_t)(sep_w < (int)sizeof line ? sep_w + 1 + : (int)sizeof line)); + int64_t active_count = 0; + for (size_t i = 0; i < n; i++) { + char path[64]; + snprintf(path, sizeof path, "result.items.%zu.number", i); + char *number = jstr_dup(resp, path); + snprintf(path, sizeof path, "result.items.%zu.name", i); + char *name = jstr_dup(resp, path); + snprintf(path, sizeof path, "result.items.%zu.type", i); + char *type = jstr_dup(resp, path); + snprintf(path, sizeof path, "result.items.%zu.active", i); + int active = jbool_val(resp, path, 0); + snprintf(path, sizeof path, "result.items.%zu.sru_code", i); + char *sru = jstr_dup(resp, path); + snprintf(path, sizeof path, "result.items.%zu.vat_code", i); + char *vat = jstr_dup(resp, path); + char ncol[512]; + char vatbuf[32]; + char tibuf[32]; + snprintf(ncol, sizeof ncol, "%s", name ? name : ""); + tui_pad_field(ncol, sizeof ncol, name_w); + snprintf(tibuf, sizeof tibuf, "%s", type_sv(type)); + tui_pad_field(tibuf, sizeof tibuf, 12); + snprintf(line, sizeof line, "%-6s %s %s %-5s %-6s %-8s\n", + number ? number : "", ncol, tibuf, + active ? "ja" : "nej", sru ? sru : "", + vat_display(name, vat, vatbuf, sizeof vatbuf)); + buf_append(&text, line, strlen(line)); + if (active) + active_count++; + free(number); + free(name); + free(type); + free(sru); + free(vat); + } + snprintf(line, sizeof line, "\n%lld konton, varav %lld aktiva.\n", + (long long)n, (long long)active_count); + buf_append(&text, line, strlen(line)); + buf_append(&text, "\0", 1); + int again = tui_pager("Kontolista", (char *)text.p, NULL); + buf_free(&text); + free(resp); + if (!again) + return; + } +} |
