From 0241122e05ac0bd174d4ec43a5882397c146aa89 Mon Sep 17 00:00:00 2001 From: Anders Betts Date: Thu, 17 Sep 2026 22:54:18 +0200 Subject: Implement org.update (owner) and cover it in tests --- src/commands.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) (limited to 'src') diff --git a/src/commands.c b/src/commands.c index 5ccadfc..948c42c 100644 --- a/src/commands.c +++ b/src/commands.c @@ -675,6 +675,94 @@ static yyjson_mut_val *h_org_get(struct req *r) return o; } +static yyjson_mut_val *h_org_update(struct req *r) +{ + const char *name = arg_str(r->args, "name"); + const char *org_nr = arg_str(r->args, "org_nr"); + const char *vat_nr = arg_str(r->args, "vat_nr"); + const char *address = arg_str(r->args, "address"); + const char *postal = arg_str(r->args, "postal_code"); + const char *city = arg_str(r->args, "city"); + const char *country = arg_str(r->args, "country"); + const char *email = arg_str(r->args, "email"); + const char *phone = arg_str(r->args, "phone"); + const char *moms = arg_str(r->args, "moms_period"); + const char *framework = arg_str(r->args, "framework"); + int64_t fy_month = 0; + arg_int(r->args, "fiscal_year_start_month", &fy_month); + if (!name && !org_nr && !vat_nr && !address && !postal && !city && + !country && !email && !phone && !moms && !framework && fy_month == 0) + return fail(r, "INVALID_ARGS", "nothing to update"); + if (name && !*name) + return fail(r, "INVALID_ARGS", "name cannot be empty"); + if (fy_month && (fy_month < 1 || fy_month > 12)) + return fail(r, "INVALID_ARGS", "fiscal_year_start_month must be 1-12"); + if (moms && strcmp(moms, "month") != 0 && strcmp(moms, "quarter") != 0 && + strcmp(moms, "year") != 0) + return fail(r, "INVALID_ARGS", "moms_period must be month, quarter or year"); + if (framework && strcmp(framework, "K2") != 0 && + strcmp(framework, "K3") != 0) + return fail(r, "INVALID_ARGS", "framework must be K2 or K3"); + + sqlite3_stmt *st = NULL; + if (sqlite3_prepare_v2( + r->db, + "UPDATE orgs SET" + " name=COALESCE(?2,name), org_nr=COALESCE(?3,org_nr)," + " vat_nr=COALESCE(?4,vat_nr), address=COALESCE(?5,address)," + " postal_code=COALESCE(?6,postal_code), city=COALESCE(?7,city)," + " country=COALESCE(?8,country), email=COALESCE(?9,email)," + " phone=COALESCE(?10,phone)," + " fiscal_year_start_month=CASE WHEN ?11=0" + " THEN fiscal_year_start_month ELSE ?11 END," + " moms_period=COALESCE(?12,moms_period)," + " framework=COALESCE(?13,framework)" + " WHERE id=?1", + -1, &st, NULL) != SQLITE_OK) + return fail(r, "INTERNAL", "database error"); + sqlite3_bind_int64(st, 1, r->org_id); + const char *texts[9] = { name, org_nr, vat_nr, address, postal, + city, country, email, phone }; + for (int i = 0; i < 9; i++) { + if (texts[i]) + sqlite3_bind_text(st, i + 2, texts[i], -1, SQLITE_TRANSIENT); + else + sqlite3_bind_null(st, i + 2); + } + sqlite3_bind_int64(st, 11, fy_month); + if (moms) + sqlite3_bind_text(st, 12, moms, -1, SQLITE_TRANSIENT); + else + sqlite3_bind_null(st, 12); + if (framework) + sqlite3_bind_text(st, 13, framework, -1, SQLITE_TRANSIENT); + else + sqlite3_bind_null(st, 13); + int rc = sqlite3_step(st); + sqlite3_finalize(st); + if (rc != SQLITE_DONE) + return fail(r, "INTERNAL", sqlite3_errmsg(r->db)); + + char *reqjson = audit_args_json(r->args); + audit_append(r->db, r->org_id, r->sess->user_id, r->sess->token_id, + "org.update", reqjson, "OK", NULL); + free(reqjson); + + st = NULL; + if (sqlite3_prepare_v2(r->db, "SELECT " ORG_COLUMNS + " FROM orgs WHERE id=?1", + -1, &st, NULL) != SQLITE_OK) + return fail(r, "INTERNAL", "database error"); + sqlite3_bind_int64(st, 1, r->org_id); + yyjson_mut_val *o = NULL; + if (sqlite3_step(st) == SQLITE_ROW) + o = org_json(r, st); + sqlite3_finalize(st); + if (!o) + return fail(r, "NOT_FOUND", "org not found"); + return o; +} + static yyjson_mut_val *h_org_member_list(struct req *r) { yyjson_mut_val *items = yyjson_mut_arr(r->rdoc); @@ -3572,6 +3660,8 @@ const struct command g_commands[] = { { "org.list", "List orgs for the current user", PERM_READ, 0, 0, 0, h_org_list }, { "org.get", "Get org details", PERM_READ, 1, 0, 0, h_org_get }, + { "org.update", "Update org details (owner)", PERM_OWNER, 1, 1, 1, + h_org_update }, { "org.member_list", "List org members", PERM_READ, 1, 0, 0, h_org_member_list }, { "org.member_add", "Add a member to the org", PERM_OWNER, 1, 1, 1, -- cgit v1.3