aboutsummaryrefslogtreecommitdiff
path: root/clients/screens_accounts.c
diff options
context:
space:
mode:
Diffstat (limited to 'clients/screens_accounts.c')
-rw-r--r--clients/screens_accounts.c173
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;
+ }
+}