aboutsummaryrefslogtreecommitdiff
path: root/src/cmd_reports.c
diff options
context:
space:
mode:
authorAnders Betts <anders.betts@gmail.com>2026-09-20 20:11:19 +0200
committerAnders Betts <anders.betts@gmail.com>2026-09-20 20:11:19 +0200
commit8351fa7752bb8341ef405a37ff7c73142715e981 (patch)
treedde603d313f4f26934f2ce20a22dfd9b69324cf0 /src/cmd_reports.c
parentbeafdbe0d64340387d619c38554976410129f05b (diff)
downloadbokf-8351fa7752bb8341ef405a37ff7c73142715e981.tar.gz
bokf-8351fa7752bb8341ef405a37ff7c73142715e981.zip
commands: split the command table by domain
Diffstat (limited to 'src/cmd_reports.c')
-rw-r--r--src/cmd_reports.c209
1 files changed, 209 insertions, 0 deletions
diff --git a/src/cmd_reports.c b/src/cmd_reports.c
new file mode 100644
index 0000000..a7be995
--- /dev/null
+++ b/src/cmd_reports.c
@@ -0,0 +1,209 @@
+#include "commands.h"
+#include "cmd_util.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "db.h"
+#include "reports.h"
+#include "util.h"
+
+/* ------------------------------------------------------------------ */
+/* reports and SIE */
+/* ------------------------------------------------------------------ */
+
+static yyjson_mut_val *h_report_trial_balance(struct req *r)
+{
+ int64_t fy = 0;
+ if (req_fy(r, &fy) != 0)
+ return NULL;
+ int include_zero = 0;
+ arg_bool(r->args, "include_zero", &include_zero);
+ char *err = NULL;
+ yyjson_mut_val *res = report_trial_balance(
+ r->rdoc, r->db, r->org_id, fy, arg_str(r->args, "from"),
+ arg_str(r->args, "to"), include_zero, &err);
+ if (!res) {
+ yyjson_mut_val *e = fail(r, "INTERNAL", err ? err : "report failed");
+ free(err);
+ return e;
+ }
+ return res;
+}
+
+static yyjson_mut_val *h_report_income_statement(struct req *r)
+{
+ int64_t fy = 0;
+ if (req_fy(r, &fy) != 0)
+ return NULL;
+ char *err = NULL;
+ yyjson_mut_val *res = report_income_statement(
+ r->rdoc, r->db, r->org_id, fy, arg_str(r->args, "from"),
+ arg_str(r->args, "to"), &err);
+ if (!res) {
+ yyjson_mut_val *e = fail(r, "INTERNAL", err ? err : "report failed");
+ free(err);
+ return e;
+ }
+ return res;
+}
+
+static yyjson_mut_val *h_report_balance_sheet(struct req *r)
+{
+ int64_t fy = 0;
+ if (req_fy(r, &fy) != 0)
+ return NULL;
+ char *err = NULL;
+ yyjson_mut_val *res = report_balance_sheet(
+ r->rdoc, r->db, r->org_id, fy, arg_str(r->args, "to"), &err);
+ if (!res) {
+ yyjson_mut_val *e = fail(r, "INTERNAL", err ? err : "report failed");
+ free(err);
+ return e;
+ }
+ return res;
+}
+
+static yyjson_mut_val *h_report_vat(struct req *r)
+{
+ const char *from = arg_str(r->args, "from");
+ const char *to = arg_str(r->args, "to");
+ if (!from || !to)
+ return fail(r, "INVALID_ARGS", "from and to are required");
+ char *err = NULL;
+ yyjson_mut_val *res =
+ report_vat(r->rdoc, r->db, r->org_id, from, to, &err);
+ if (!res) {
+ yyjson_mut_val *e = fail(r, "INTERNAL", err ? err : "report failed");
+ free(err);
+ return e;
+ }
+ return res;
+}
+
+static yyjson_mut_val *h_report_general_ledger(struct req *r)
+{
+ int64_t fy = 0;
+ if (req_fy(r, &fy) != 0)
+ return NULL;
+ yyjson_val *accounts = yyjson_obj_get(r->args, "accounts");
+ if (accounts && !yyjson_is_arr(accounts))
+ return fail(r, "INVALID_ARGS", "accounts must be an array of strings");
+ char *err = NULL;
+ yyjson_mut_val *res = report_general_ledger(
+ r->rdoc, r->db, r->org_id, fy, arg_str(r->args, "from"),
+ arg_str(r->args, "to"), accounts, &err);
+ if (!res) {
+ yyjson_mut_val *e = fail(r, "INTERNAL", err ? err : "report failed");
+ free(err);
+ return e;
+ }
+ return res;
+}
+
+static yyjson_mut_val *h_report_voucher_list(struct req *r)
+{
+ int64_t fy = 0;
+ if (req_fy(r, &fy) != 0)
+ return NULL;
+ char *err = NULL;
+ yyjson_mut_val *res = report_voucher_list(
+ r->rdoc, r->db, r->org_id, fy, arg_str(r->args, "series"), &err);
+ if (!res) {
+ yyjson_mut_val *e = fail(r, "INTERNAL", err ? err : "report failed");
+ free(err);
+ return e;
+ }
+ return res;
+}
+
+static yyjson_mut_val *h_report_vat_eskd(struct req *r)
+{
+ const char *from = arg_str(r->args, "from");
+ const char *to = arg_str(r->args, "to");
+ if (!from || !to)
+ return fail(r, "INVALID_ARGS", "from and to are required");
+ char *err = NULL;
+ yyjson_mut_val *res =
+ report_vat_eskd(r->rdoc, r->db, r->org_id, from, to,
+ arg_str(r->args, "upplysning"), &err);
+ if (!res) {
+ yyjson_mut_val *e = fail(r, "INVALID_ARGS",
+ err ? err : "could not build the eSKD file");
+ free(err);
+ return e;
+ }
+ return res;
+}
+
+
+static const struct cmd_arg args_report_trial_balance[] = {
+ { "fiscal_year", ARG_INT, 0, NULL, NULL,
+ "Fiscal year id; defaults to the latest" },
+ { "from", ARG_DATE, 0, NULL, NULL, "Narrow the period" },
+ { "to", ARG_DATE, 0, NULL, NULL, "Narrow the period" },
+ { "include_zero", ARG_BOOL, 0, "false", NULL,
+ "Include accounts with no activity" },
+};
+
+static const struct cmd_arg args_report_income_statement[] = {
+ { "fiscal_year", ARG_INT, 0, NULL, NULL,
+ "Fiscal year id; defaults to the latest" },
+ { "from", ARG_DATE, 0, NULL, NULL, "Narrow the period" },
+ { "to", ARG_DATE, 0, NULL, NULL, "Narrow the period" },
+};
+
+static const struct cmd_arg args_report_balance_sheet[] = {
+ { "fiscal_year", ARG_INT, 0, NULL, NULL,
+ "Fiscal year id; defaults to the latest" },
+ { "to", ARG_DATE, 0, NULL, NULL, "Report through this date" },
+};
+
+static const struct cmd_arg args_report_vat[] = {
+ { "from", ARG_DATE, 1, NULL, NULL, "Period start" },
+ { "to", ARG_DATE, 1, NULL, NULL, "Period end" },
+};
+
+static const struct cmd_arg args_report_general_ledger[] = {
+ { "fiscal_year", ARG_INT, 0, NULL, NULL,
+ "Fiscal year id; defaults to the latest" },
+ { "accounts", ARG_JSON, 0, NULL, NULL,
+ "Array of account numbers to include" },
+ { "from", ARG_DATE, 0, NULL, NULL, "Narrow the period" },
+ { "to", ARG_DATE, 0, NULL, NULL, "Narrow the period" },
+};
+
+static const struct cmd_arg args_report_voucher_list[] = {
+ { "fiscal_year", ARG_INT, 0, NULL, NULL,
+ "Fiscal year id; defaults to the latest" },
+ { "series", ARG_STR, 0, NULL, NULL, "Number series filter" },
+};
+
+static const struct cmd_arg args_report_vat_eskd[] = {
+ { "from", ARG_DATE, 1, NULL, NULL, "Period start" },
+ { "to", ARG_DATE, 1, NULL, NULL, "Period end" },
+ { "upplysning", ARG_STR, 0, NULL, NULL,
+ "Free-text message to Skatteverket" },
+};
+
+const struct command g_cmd_reports[] = {
+ { "report.trial_balance", "Saldobalans (IB, period, UB)", PERM_READ, 1, 0,
+ 0, h_report_trial_balance, CMD_ARGS(args_report_trial_balance) },
+ { "report.income_statement", "Resultaträkning", PERM_READ, 1, 0, 0,
+ h_report_income_statement, CMD_ARGS(args_report_income_statement) },
+ { "report.balance_sheet", "Balansräkning", PERM_READ, 1, 0, 0,
+ h_report_balance_sheet, CMD_ARGS(args_report_balance_sheet) },
+ { "report.vat", "Momsdeklaration ruta för ruta", PERM_READ, 1, 0, 0,
+ h_report_vat, CMD_ARGS(args_report_vat) },
+ { "report.general_ledger", "Huvudbok", PERM_READ, 1, 0, 0,
+ h_report_general_ledger, CMD_ARGS(args_report_general_ledger) },
+ { "report.voucher_list", "Verifikationslista", PERM_READ, 1, 0, 0,
+ h_report_voucher_list, CMD_ARGS(args_report_voucher_list) },
+ { "report.vat_eskd", "eSKD XML for the momsdeklaration (ISO-8859-1)",
+ PERM_READ, 1, 0, 0, h_report_vat_eskd, CMD_ARGS(args_report_vat_eskd) },
+};
+
+const struct cmd_table g_cmd_table_reports = {
+ g_cmd_reports, sizeof g_cmd_reports / sizeof g_cmd_reports[0]
+};