diff options
| author | Anders Betts <anders.betts@gmail.com> | 2026-09-22 19:53:19 +0200 |
|---|---|---|
| committer | Anders Betts <anders.betts@gmail.com> | 2026-09-22 19:55:47 +0200 |
| commit | 3f07edf64f74cab68cb379e49841fdf6b24674e9 (patch) | |
| tree | 125a350247d421b3dbac11d56c25bdf189af2656 /tests | |
| parent | 6e0e96cfc74b129950002456e21d401dd07e10fd (diff) | |
| parent | e1a24f6250f5e498e524ce14a5acbed5fc5c2a91 (diff) | |
| download | bokf-3f07edf64f74cab68cb379e49841fdf6b24674e9.tar.gz bokf-3f07edf64f74cab68cb379e49841fdf6b24674e9.zip | |
Merge eff/imported-closings; skip only SIE-imported Stäng closings
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/test_core.c | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/tests/test_core.c b/tests/test_core.c index 50dde15..018b0aa 100644 --- a/tests/test_core.c +++ b/tests/test_core.c @@ -1561,6 +1561,116 @@ static void test_reports(struct tctx *t) yyjson_doc_free(d); } +static void test_imported_closings(struct tctx *t) +{ + yyjson_doc *d; + int64_t org = 0; + + (void)t; + d = call(reqf("{\"v\":1,\"id\":\"ic1\",\"cmd\":\"org.create\"," + "\"session\":\"%s\",\"args\":{\"name\":\"Import AB\"}}", + g_session)); + CHECK_OK(d); + org = jint(d, "result.id"); + CHECK(org > 0); + 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. 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\"," + "\"session\":\"%s\",\"org\":%d}", + g_session, (int)org)); + CHECK_OK(d); + CHECK(jint(d, "result.result_ore") == 80000); + CHECK(find_amount(d, "result.revenue.accounts", "account", "3001", + "amount_ore") == 100000); + CHECK(find_amount(d, "result.expenses.accounts", "account", "5410", + "amount_ore") == 20000); + yyjson_doc_free(d); + + /* The result sits in 2099, so the balance sheet must not count it twice. */ + d = call(reqf("{\"v\":1,\"id\":\"ic7\",\"cmd\":\"report.balance_sheet\"," + "\"session\":\"%s\",\"org\":%d}", + g_session, (int)org)); + CHECK_OK(d); + /* 2640 is chart-typed as a liability (debit balance shows negative) */ + CHECK(jint(d, "result.assets.total_ore") == 100000); + CHECK(jint(d, "result.liabilities.total_ore") == 20000); + CHECK(jint(d, "result.equity.total_ore") == 80000); + CHECK(jint(d, "result.assets.total_ore") == + jint(d, "result.liabilities.total_ore") + + jint(d, "result.equity.total_ore")); + CHECK(find_amount(d, "result.equity.accounts", "account", "2099", + "amount_ore") == 80000); + yyjson_doc_free(d); + + /* the declaration path: the SRU result must not be zeroed either */ + d = call(reqf("{\"v\":1,\"id\":\"ic8\",\"cmd\":\"org.update\"," + "\"session\":\"%s\",\"org\":%d,\"args\":" + "{\"org_nr\":\"559331-2126\",\"postal_code\":\"192 48\"," + "\"city\":\"Sollentuna\"}}", + g_session, (int)org)); + CHECK_OK(d); + yyjson_doc_free(d); + + d = call(reqf("{\"v\":1,\"id\":\"ic9\",\"cmd\":\"sru.export\"," + "\"session\":\"%s\",\"org\":%d,\"args\":{}}", + g_session, (int)org)); + CHECK_OK(d); + const char *sb64 = jstr(d, "result.blanketter.content_base64"); + unsigned char *srub = NULL; + size_t srul = 0; + CHECK(sb64 && util_b64_decode(sb64, strlen(sb64), &srub, &srul) == 0); + char *sru = xmalloc(srul + 1); + memcpy(sru, srub, srul); + sru[srul] = '\0'; + free(srub); + CHECK(strstr(sru, "#UPPGIFT 7450 800") != NULL); + 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) { yyjson_doc *d; @@ -5614,6 +5724,7 @@ static const struct ttest TESTS[] = { { "vouchers", test_vouchers, "org_members" }, { "voucher_errors", test_voucher_errors, "org_members" }, { "reports", test_reports, "vouchers" }, + { "imported_closings", test_imported_closings, "org_members" }, { "general_ledger", test_general_ledger, "vouchers" }, { "voucher_list", test_voucher_list, "vouchers" }, { "vat_eskd", test_vat_eskd, "vouchers" }, |
