aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/test_core.c195
1 files changed, 159 insertions, 36 deletions
diff --git a/tests/test_core.c b/tests/test_core.c
index 1d86b2b..018b0aa 100644
--- a/tests/test_core.c
+++ b/tests/test_core.c
@@ -1575,44 +1575,30 @@ static void test_imported_closings(struct tctx *t)
CHECK(org > 0);
yyjson_doc_free(d);
- d = call(reqf("{\"v\":1,\"id\":\"ic2\",\"cmd\":\"voucher.post\","
- "\"session\":\"%s\",\"org\":%d,\"args\":{\"date\":"
- "\"2026-02-01\",\"description\":\"Försäljning\",\"rows\":["
- "{\"account\":\"1930\",\"debit_ore\":125000},"
- "{\"account\":\"3001\",\"credit_ore\":100000},"
- "{\"account\":\"2611\",\"credit_ore\":25000}]}}",
- g_session, (int)org));
- CHECK_OK(d);
- yyjson_doc_free(d);
-
- d = call(reqf("{\"v\":1,\"id\":\"ic3\",\"cmd\":\"voucher.post\","
- "\"session\":\"%s\",\"org\":%d,\"args\":{\"date\":"
- "\"2026-02-02\",\"description\":\"Inköp\",\"rows\":["
- "{\"account\":\"5410\",\"debit_ore\":20000},"
- "{\"account\":\"2640\",\"debit_ore\":5000},"
- "{\"account\":\"1930\",\"credit_ore\":25000}]}}",
- g_session, (int)org));
- CHECK_OK(d);
- yyjson_doc_free(d);
-
/* The source system closes the P&L accounts straight to 2099; the income
- statement must still show the year's real figures. */
- d = call(reqf("{\"v\":1,\"id\":\"ic4\",\"cmd\":\"voucher.post\","
- "\"session\":\"%s\",\"org\":%d,\"args\":{\"date\":"
- "\"2026-04-30\",\"description\":\"Stäng intäktskonton\","
- "\"rows\":[{\"account\":\"3001\",\"debit_ore\":100000},"
- "{\"account\":\"2099\",\"credit_ore\":100000}]}}",
- g_session, (int)org));
- CHECK_OK(d);
- yyjson_doc_free(d);
-
- d = call(reqf("{\"v\":1,\"id\":\"ic5\",\"cmd\":\"voucher.post\","
- "\"session\":\"%s\",\"org\":%d,\"args\":{\"date\":"
- "\"2026-04-30\",\"description\":\"Stäng kostnadskonton\","
- "\"rows\":[{\"account\":\"2099\",\"debit_ore\":20000},"
- "{\"account\":\"5410\",\"credit_ore\":20000}]}}",
- g_session, (int)org));
+ statement must still show the year's real figures. The file is PC8
+ (CP437) like real exports: \x84 = ä, \x94 = ö. */
+ static const char sie[] =
+ "#FLAGGA 0\n"
+ "#FORMAT PC8\n"
+ "#SIETYP 4\n"
+ "#FNAMN \"Import AB\"\n"
+ "#RAR 0 20260101 20261231\n"
+ "#VER \"V\" \"1\" 20260201 \"F\x94rs\x84" "ljning\"\n"
+ "{\n#TRANS 1930 {} 1250.00\n#TRANS 3001 {} -1000.00\n"
+ "#TRANS 2611 {} -250.00\n}\n"
+ "#VER \"V\" \"2\" 20260202 \"Ink\x94" "p\"\n"
+ "{\n#TRANS 5410 {} 200.00\n#TRANS 2640 {} 50.00\n"
+ "#TRANS 1930 {} -250.00\n}\n"
+ "#VER \"V\" \"3\" 20260430 \"St\x84" "ng intäktskonton\"\n"
+ "{\n#TRANS 3001 {} 1000.00\n#TRANS 2099 {} -1000.00\n}\n"
+ "#VER \"V\" \"4\" 20260430 \"St\x84" "ng kostnadskonton\"\n"
+ "{\n#TRANS 2099 {} 200.00\n#TRANS 5410 {} -200.00\n}\n";
+ char *sie_b64 = util_b64((const unsigned char *)sie, strlen(sie));
+ d = call_sie_import(g_session, org, sie_b64, 0);
+ free(sie_b64);
CHECK_OK(d);
+ CHECK(jint(d, "result.vouchers") == 4);
yyjson_doc_free(d);
d = call(reqf("{\"v\":1,\"id\":\"ic6\",\"cmd\":\"report.income_statement\","
@@ -1667,6 +1653,22 @@ static void test_imported_closings(struct tctx *t)
CHECK(strstr(sru, "#UPPGIFT 7650 800") != NULL);
free(sru);
yyjson_doc_free(d);
+
+ /* a voucher entered in bokf is never skipped, whatever its text */
+ d = call(reqf("{\"v\":1,\"id\":\"ic10\",\"cmd\":\"voucher.post\","
+ "\"session\":\"%s\",\"org\":%d,\"args\":{\"date\":"
+ "\"2026-05-02\",\"description\":\"Stängsel\",\"rows\":["
+ "{\"account\":\"1930\",\"debit_ore\":100},"
+ "{\"account\":\"3001\",\"credit_ore\":100}]}}",
+ g_session, (int)org));
+ CHECK_OK(d);
+ yyjson_doc_free(d);
+ d = call(reqf("{\"v\":1,\"id\":\"ic11\",\"cmd\":\"report.income_statement\","
+ "\"session\":\"%s\",\"org\":%d}",
+ g_session, (int)org));
+ CHECK_OK(d);
+ CHECK(jint(d, "result.result_ore") == 80100);
+ yyjson_doc_free(d);
}
static void test_general_ledger(struct tctx *t)
@@ -2175,6 +2177,126 @@ static void test_ib(struct tctx *t)
yyjson_doc_free(d);
}
+/* Opening balances carry earlier years' IB vouchers; P&L accounts restart
+ at every year start (reports and SIE export). */
+static void test_ib_carry(struct tctx *t)
+{
+ (void)t;
+ yyjson_doc *d;
+
+ d = call(reqf("{\"v\":1,\"id\":\"ibc1\",\"cmd\":\"org.create\","
+ "\"session\":\"%s\",\"args\":{\"name\":\"Överföring AB\"}}",
+ g_session));
+ CHECK_OK(d);
+ int org = (int)jint(d, "result.id");
+ yyjson_doc_free(d);
+ d = call(reqf("{\"v\":1,\"id\":\"ibc2\",\"cmd\":\"fiscal_year.list\","
+ "\"session\":\"%s\",\"org\":%d}",
+ g_session, org));
+ CHECK_OK(d);
+ char start[11] = "", end[11] = "";
+ snprintf(start, sizeof start, "%s", jstr(d, "result.items.0.start_date"));
+ snprintf(end, sizeof end, "%s", jstr(d, "result.items.0.end_date"));
+ yyjson_doc_free(d);
+ int y = atoi(end) + 1;
+
+ const char *posts[][4] = {
+ { start, "IB", "1940", "2010" },
+ { start, "V", "1930", "3001" },
+ { end, "V", "8999", "2099" },
+ };
+ const int64_t amounts[] = { 2500000, 100000, 100000 };
+ for (size_t i = 0; i < 3; i++) {
+ d = call(reqf("{\"v\":1,\"id\":\"ibc3\",\"cmd\":\"voucher.post\","
+ "\"session\":\"%s\",\"org\":%d,\"args\":{\"date\":"
+ "\"%s\",\"description\":\"År 1\",\"series\":\"%s\","
+ "\"rows\":[{\"account\":\"%s\",\"debit_ore\":%lld},"
+ "{\"account\":\"%s\",\"credit_ore\":%lld}]}}",
+ g_session, org, posts[i][0], posts[i][1], posts[i][2],
+ (long long)amounts[i], posts[i][3],
+ (long long)amounts[i]));
+ CHECK_OK(d);
+ yyjson_doc_free(d);
+ }
+
+ d = call(reqf("{\"v\":1,\"id\":\"ibc4\",\"cmd\":\"fiscal_year.open\","
+ "\"session\":\"%s\",\"org\":%d,\"args\":{\"label\":\"%d\","
+ "\"start_date\":\"%d-01-01\",\"end_date\":\"%d-12-31\"}}",
+ g_session, org, y, y, y));
+ CHECK_OK(d);
+ int64_t fy2 = jint(d, "result.id");
+ yyjson_doc_free(d);
+ d = call(reqf("{\"v\":1,\"id\":\"ibc5\",\"cmd\":\"voucher.post\","
+ "\"session\":\"%s\",\"org\":%d,\"args\":{\"date\":"
+ "\"%d-02-01\",\"description\":\"År 2\",\"rows\":"
+ "[{\"account\":\"1930\",\"debit_ore\":5000},"
+ "{\"account\":\"3001\",\"credit_ore\":5000}]}}",
+ g_session, org, y));
+ CHECK_OK(d);
+ yyjson_doc_free(d);
+
+ d = call(reqf("{\"v\":1,\"id\":\"ibc6\",\"cmd\":\"report.trial_balance\","
+ "\"session\":\"%s\",\"org\":%d,\"args\":{\"fiscal_year\":"
+ "%lld}}",
+ g_session, org, (long long)fy2));
+ CHECK_OK(d);
+ CHECK(find_amount(d, "result.accounts", "account", "1940", "ib_ore") ==
+ 2500000);
+ CHECK(find_amount(d, "result.accounts", "account", "2010", "ib_ore") ==
+ -2500000);
+ CHECK(find_amount(d, "result.accounts", "account", "2099", "ib_ore") ==
+ -100000);
+ CHECK(find_amount(d, "result.accounts", "account", "3001", "ib_ore") == 0);
+ CHECK(find_amount(d, "result.accounts", "account", "8999", "ib_ore") == -1);
+ CHECK(jint(d, "result.totals.ib_ore") == 0);
+ yyjson_doc_free(d);
+
+ d = call(reqf("{\"v\":1,\"id\":\"ibc7\",\"cmd\":\"report.trial_balance\","
+ "\"session\":\"%s\",\"org\":%d,\"args\":{\"fiscal_year\":"
+ "%lld,\"from\":\"%d-03-01\"}}",
+ g_session, org, (long long)fy2, y));
+ CHECK_OK(d);
+ CHECK(find_amount(d, "result.accounts", "account", "3001", "ib_ore") ==
+ -5000);
+ CHECK(find_amount(d, "result.accounts", "account", "1930", "ib_ore") ==
+ 105000);
+ yyjson_doc_free(d);
+
+ d = call(reqf("{\"v\":1,\"id\":\"ibc8\",\"cmd\":\"report.balance_sheet\","
+ "\"session\":\"%s\",\"org\":%d,\"args\":{\"fiscal_year\":"
+ "%lld}}",
+ g_session, org, (long long)fy2));
+ CHECK_OK(d);
+ CHECK(find_amount(d, "result.equity.accounts", "account", "2010",
+ "amount_ore") == 2500000);
+ CHECK(jint(d, "result.assets.total_ore") == 2605000);
+ CHECK(jint(d, "result.assets.total_ore") ==
+ jint(d, "result.liabilities.total_ore") +
+ jint(d, "result.equity.total_ore"));
+ yyjson_doc_free(d);
+
+ d = call(reqf("{\"v\":1,\"id\":\"ibc9\",\"cmd\":\"sie.export\","
+ "\"session\":\"%s\",\"org\":%d,\"args\":{\"fiscal_year\":"
+ "%lld}}",
+ g_session, org, (long long)fy2));
+ CHECK_OK(d);
+ FILE *sf = fopen(jstr(d, "result.path"), "rb");
+ yyjson_doc_free(d);
+ CHECK(sf != NULL);
+ if (sf) {
+ char sbuf[65536];
+ size_t sn = fread(sbuf, 1, sizeof sbuf - 1, sf);
+ sbuf[sn] = '\0';
+ fclose(sf);
+ CHECK(strstr(sbuf, "#IB 0 2010 -25000.00") != NULL);
+ CHECK(strstr(sbuf, "#UB 0 1930 1050.00") != NULL);
+ CHECK(strstr(sbuf, "#RES 0 3001 -50.00") != NULL);
+ CHECK(strstr(sbuf, "#IB 0 3001") == NULL);
+ CHECK(strstr(sbuf, "#UB 0 3001") == NULL);
+ CHECK(strstr(sbuf, "#RES 0 1930") == NULL);
+ }
+}
+
static void test_period_lock(struct tctx *t)
{
yyjson_doc *d;
@@ -5611,6 +5733,7 @@ static const struct ttest TESTS[] = {
{ "attachments", test_attachments, "vouchers idempotency" },
{ "templates", test_templates, "org_members" },
{ "ib", test_ib, "org_members" },
+ { "ib_carry", test_ib_carry, "org_members" },
{ "period_lock", test_period_lock, "fiscal_years" },
{ "sie_export", test_sie_export, "ib" },
{ "sie_import", test_sie_import, "attachments sie_export" },