diff options
| author | Anders Betts <anders.betts@gmail.com> | 2026-09-18 21:07:38 +0200 |
|---|---|---|
| committer | Anders Betts <anders.betts@gmail.com> | 2026-09-18 21:07:38 +0200 |
| commit | 0ec59a0dfce8d350f26783ccc2456e5cb68c37a5 (patch) | |
| tree | 69a9764e8d75df8d33aebe1b5a18e95909e4f9a4 /src/commands.c | |
| parent | a5d3ddf6d512bc459cfa450c6b449c2e7a245373 (diff) | |
| download | bokf-0ec59a0dfce8d350f26783ccc2456e5cb68c37a5.tar.gz bokf-0ec59a0dfce8d350f26783ccc2456e5cb68c37a5.zip | |
reports: huvudbok and verifikationslista; fiscal_year.reopen
report.general_ledger lists every account with activity or IB, its
postings in date order with a running saldo, and Omslutning/Utgående
saldo; accounts?/from?/to? narrow it. report.voucher_list lists the
year's vouchers with rows and totals, with an optional series filter.
fiscal_year.reopen undoes a close (owner-only, confirm:true, audited) so
the Räkenskapsår screen can toggle the status.
Diffstat (limited to 'src/commands.c')
| -rw-r--r-- | src/commands.c | 81 |
1 files changed, 79 insertions, 2 deletions
diff --git a/src/commands.c b/src/commands.c index 64212f7..1034b31 100644 --- a/src/commands.c +++ b/src/commands.c @@ -1842,6 +1842,41 @@ static yyjson_mut_val *h_fiscal_year_close(struct req *r) return yyjson_mut_obj(r->rdoc); } +static yyjson_mut_val *h_fiscal_year_reopen(struct req *r) +{ + int64_t id = 0; + int confirm = 0; + arg_int(r->args, "id", &id); + arg_bool(r->args, "confirm", &confirm); + if (id <= 0 || !confirm) + return fail(r, "INVALID_ARGS", "id and confirm:true are required"); + if (r->dry_run) { + yyjson_mut_val *o = yyjson_mut_obj(r->rdoc); + yyjson_mut_obj_add_bool(r->rdoc, o, "dry_run", true); + return o; + } + sqlite3_stmt *st = NULL; + if (sqlite3_prepare_v2( + r->db, + "UPDATE fiscal_years SET status='open', closed_at=NULL," + " closed_by=NULL WHERE org_id=?1 AND id=?2 AND status='closed'", + -1, &st, NULL) != SQLITE_OK) + return fail(r, "INTERNAL", "database error"); + sqlite3_bind_int64(st, 1, r->org_id); + sqlite3_bind_int64(st, 2, id); + int rc = sqlite3_step(st); + sqlite3_finalize(st); + if (rc != SQLITE_DONE) + return fail(r, "INTERNAL", sqlite3_errmsg(r->db)); + if (sqlite3_changes(r->db) == 0) + return fail(r, "NOT_FOUND", "closed fiscal year not found"); + char *reqjson = audit_args_json(r->args); + audit_append(r->db, r->org_id, r->sess->user_id, r->sess->token_id, + "fiscal_year.reopen", reqjson, "OK", NULL); + free(reqjson); + return yyjson_mut_obj(r->rdoc); +} + static yyjson_mut_val *h_period_lock(struct req *r) { int64_t fy = 0; @@ -3529,6 +3564,42 @@ static yyjson_mut_val *h_report_vat(struct req *r) 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 unsigned char *read_file(const char *path, size_t *out_len) { FILE *f = fopen(path, "rb"); @@ -3723,8 +3794,10 @@ const struct command g_commands[] = { h_fiscal_year_get }, { "fiscal_year.open", "Open a new fiscal year", PERM_OWNER, 1, 1, 1, h_fiscal_year_open }, - { "fiscal_year.close", "Close a fiscal year (irreversible)", PERM_OWNER, 1, - 1, 0, h_fiscal_year_close }, + { "fiscal_year.close", "Close a fiscal year", PERM_OWNER, 1, 1, 0, + h_fiscal_year_close }, + { "fiscal_year.reopen", "Reopen a closed fiscal year", PERM_OWNER, 1, 1, 1, + h_fiscal_year_reopen }, { "period.lock", "Lock a period through a date", PERM_OWNER, 1, 1, 1, h_period_lock }, { "period.unlock", "Remove a period lock", PERM_OWNER, 1, 1, 1, @@ -3764,6 +3837,10 @@ const struct command g_commands[] = { h_report_balance_sheet }, { "report.vat", "Momsdeklaration ruta för ruta", PERM_READ, 1, 0, 0, h_report_vat }, + { "report.general_ledger", "Huvudbok", PERM_READ, 1, 0, 0, + h_report_general_ledger }, + { "report.voucher_list", "Verifikationslista", PERM_READ, 1, 0, 0, + h_report_voucher_list }, { "sie.export", "Export SIE 4 (PC8)", PERM_READ, 1, 0, 0, h_sie_export }, { "sie.import", "Import SIE 4 into an empty fiscal year", PERM_WRITE, 1, 1, 1, h_sie_import }, |
