From 5f25180b3d79d9a03952217cd77a16601ae0a6d0 Mon Sep 17 00:00:00 2001 From: Aldrik Ramaekers Date: Sat, 25 Oct 2025 15:00:38 +0200 Subject: refactor tax rate loading --- TODO | 4 --- include/administration.hpp | 14 +++++---- src/administration.cpp | 47 +++++++++++++++++++------------ src/administration_reader.cpp | 3 -- src/ai_providers/openAI.cpp | 1 + src/importer.cpp | 5 ++-- src/ui/ui_settings.cpp | 6 ++-- tests/administration_rw_tests.cpp | 2 +- tests/administration_validation_tests.cpp | 2 +- tests/test_helper.cpp | 4 +-- 10 files changed, 48 insertions(+), 40 deletions(-) diff --git a/TODO b/TODO index 16d71f8..55452bb 100644 --- a/TODO +++ b/TODO @@ -10,10 +10,6 @@ Improvements: - "price includes tax" toggle that recalculates billing item tax, net and total - add every country to country list. should be toggleable wether a country can receive invoices. should be listed in file countries/_unimplemented.cpp. - Loading animation on save button while file is being saved. navigation should be disabled untill file is saved. -- Load all tax rates from all countries into new list, should be loaded before a file is imported. We can get rid of invoice_recalculate_totals after this. -- AI importer: file path should not be editable as it is imported -- AI importer: real error logging for OpenAI and importing in general -- AI importer: log elapsed time for ai requests Features: - Handle invalid api key response from AI backends and display in settings UI diff --git a/include/administration.hpp b/include/administration.hpp index f13f4fb..3fc68bd 100644 --- a/include/administration.hpp +++ b/include/administration.hpp @@ -408,7 +408,8 @@ typedef struct list_t contacts; list_t projects; - list_t tax_rates; + list_t tax_rates; // Enabled tax rates. + list_t all_tax_rates; // Tax rates for all countries. list_t cost_centers; u32 invoice_count; @@ -533,11 +534,15 @@ namespace administration { u32 tax_rate_count(); tax_rate tax_rate_create_empty(); a_err tax_rate_import(tax_rate data); - a_err tax_rate_add(tax_rate data); - a_err tax_rate_exists(tax_rate data); - a_err tax_rate_remove(tax_rate data); + a_err tax_rate_enable(tax_rate data); + a_err tax_rate_is_enabled(tax_rate data); + a_err tax_rate_disable(tax_rate data); + /// @brief Find tax rate by internal code, across all available tax rates. a_err tax_rate_get_by_internal_code(tax_rate* buffer, char* id); + + /// @brief Get all enabled tax rates. + /// @return tax rate count u32 tax_rate_get_all(tax_rate* buffer, tax_rate_type type); // Cost center functions. @@ -567,7 +572,6 @@ namespace administration { invoice invoice_create_copy(invoice* invoice); void invoice_destroy(invoice* invoice); - void invoice_recalculate_totals(); a_err invoice_is_valid(invoice* invoice); bool invoice_has_intra_community_services(invoice* invoice); diff --git a/src/administration.cpp b/src/administration.cpp index b1e3198..d51b1b9 100644 --- a/src/administration.cpp +++ b/src/administration.cpp @@ -130,11 +130,27 @@ void administration_create() list_init(&g_administration.contacts); list_init(&g_administration.projects); list_init(&g_administration.tax_rates); + list_init(&g_administration.all_tax_rates); list_init(&g_administration.cost_centers); strops::copy(g_administration.path, "", sizeof(g_administration.path)); memops::zero(&g_administration.ai_service, sizeof(ai_service)); + // Load all tax rates. + for (s32 i = 0; i < country::get_count(); i++) + { + tax_rate* tax_rates = (tax_rate*)memops::alloc(sizeof(tax_rate) * 400); + u32 tax_rate_count = country::get_available_tax_rates(country::get_code_by_index(i), tax_rates, 400); + + for (u32 x = 0; x < tax_rate_count; x++) + { + tax_rate* rate = (tax_rate*)memops::alloc(sizeof(tax_rate)); + memops::copy(rate, &tax_rates[x], sizeof(tax_rate)); + + list_append(&g_administration.all_tax_rates, rate); + } + } + logger::info("Setup took %.3fms.", STOPWATCH_TIME); } @@ -167,6 +183,7 @@ void administration::destroy() administration_destroy_list(&g_administration.contacts); administration_destroy_list(&g_administration.projects); administration_destroy_list(&g_administration.tax_rates); + administration_destroy_list(&g_administration.all_tax_rates); administration_destroy_list(&g_administration.cost_centers); } @@ -1054,7 +1071,7 @@ tax_rate administration::tax_rate_create_empty() return result; } -a_err administration::tax_rate_remove(tax_rate data) +a_err administration::tax_rate_disable(tax_rate data) { list_iterator_start(&g_administration.tax_rates); while (list_iterator_hasnext(&g_administration.tax_rates)) { @@ -1077,7 +1094,7 @@ a_err administration::tax_rate_remove(tax_rate data) return A_ERR_NOT_FOUND; } -a_err administration::tax_rate_exists(tax_rate data) +a_err administration::tax_rate_is_enabled(tax_rate data) { list_iterator_start(&g_administration.tax_rates); while (list_iterator_hasnext(&g_administration.tax_rates)) { @@ -1098,17 +1115,17 @@ a_err administration::tax_rate_get_by_internal_code(tax_rate* buffer, char* id) { assert(buffer); - list_iterator_start(&g_administration.tax_rates); - while (list_iterator_hasnext(&g_administration.tax_rates)) { - tax_rate c = *(tax_rate *)list_iterator_next(&g_administration.tax_rates); + list_iterator_start(&g_administration.all_tax_rates); + while (list_iterator_hasnext(&g_administration.all_tax_rates)) { + tax_rate c = *(tax_rate *)list_iterator_next(&g_administration.all_tax_rates); if (strops::equals(c.internal_code, id)) { *buffer = c; - list_iterator_stop(&g_administration.tax_rates); + list_iterator_stop(&g_administration.all_tax_rates); return A_ERR_SUCCESS; } } - list_iterator_stop(&g_administration.tax_rates); + list_iterator_stop(&g_administration.all_tax_rates); return A_ERR_NOT_FOUND; } @@ -1131,7 +1148,7 @@ a_err administration::tax_rate_import(tax_rate data) return A_ERR_SUCCESS; } -a_err administration::tax_rate_add(tax_rate data) +a_err administration::tax_rate_enable(tax_rate data) { tax_rate* tb = (tax_rate*)memops::alloc(sizeof(tax_rate)); if (!tb) return A_ERR_GENERIC; @@ -1575,16 +1592,6 @@ invoice administration::invoice_create_copy(invoice* inv) return new_inv; } -void administration::invoice_recalculate_totals() -{ - list_iterator_start(&g_administration.invoices); - while (list_iterator_hasnext(&g_administration.invoices)) { - invoice* c = (invoice *)list_iterator_next(&g_administration.invoices); - administration_recalculate_invoice_totals(c); - } - list_iterator_stop(&g_administration.invoices); -} - u32 administration::invoice_count() { return list_size(&g_administration.invoices); @@ -1775,6 +1782,10 @@ static void administration_recalculate_billing_item_totals(billing_item* item) { item->tax = item->net * (rate.rate/100.0f); } + else + { + assert(0); + } item->total = item->net + item->tax; } diff --git a/src/administration_reader.cpp b/src/administration_reader.cpp index 91325ea..80d0eac 100644 --- a/src/administration_reader.cpp +++ b/src/administration_reader.cpp @@ -116,9 +116,6 @@ bool administration_reader::open_existing(char* file_path) zip_close(zip); - // Tax rates might be loaded after invoices so we need to recalculate all totals. - administration::invoice_recalculate_totals(); - logger::info("Imported '%s' in %.3fms.", file_path, STOPWATCH_TIME); return true; diff --git a/src/ai_providers/openAI.cpp b/src/ai_providers/openAI.cpp index 64e7a6a..3e5104d 100644 --- a/src/ai_providers/openAI.cpp +++ b/src/ai_providers/openAI.cpp @@ -30,6 +30,7 @@ static bool _openAI_batch_query_with_file(char** queries, size_t query_count, ch httplib::SSLClient cli("api.openai.com", 443); thrd_t threads[20]; + assert(query_count <= 20); for (u32 i = 0; i < query_count; i++) { diff --git a/src/importer.cpp b/src/importer.cpp index 4f78d20..e3d8048 100644 --- a/src/importer.cpp +++ b/src/importer.cpp @@ -257,9 +257,8 @@ static int _ai_document_to_invoice_t(void *arg) inv.status = invoice_status::INVOICE_RECEIVED; - // Set customer or supplier depending on incomming or outgoing. - contact my_info = administration::company_info_get(); - //memops::copy(&inv.customer, &my_info, sizeof(contact)); + inv.is_triangulation = !memops::equals(&inv.addressee.address, &inv.customer.address, sizeof(address)); + strops::copy(inv.customer.id, MY_COMPANY_ID, MAX_LEN_ID); // Project and cost centers cannot be interpreted from file so are set to 0. diff --git a/src/ui/ui_settings.cpp b/src/ui/ui_settings.cpp index 51beafe..2a310d3 100644 --- a/src/ui/ui_settings.cpp +++ b/src/ui/ui_settings.cpp @@ -85,10 +85,10 @@ static void draw_vat_rates() ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); - bool toggle = administration::tax_rate_exists(c) == A_ERR_SUCCESS; + bool toggle = administration::tax_rate_is_enabled(c) == A_ERR_SUCCESS; if (ImGui::Checkbox("##toggle", &toggle)) { - if (toggle) administration::tax_rate_add(c); - else administration::tax_rate_remove(c); + if (toggle) administration::tax_rate_enable(c); + else administration::tax_rate_disable(c); } char localized_code[MAX_LEN_LONG_DESC]; diff --git a/tests/administration_rw_tests.cpp b/tests/administration_rw_tests.cpp index 224a689..794c12a 100644 --- a/tests/administration_rw_tests.cpp +++ b/tests/administration_rw_tests.cpp @@ -33,7 +33,7 @@ TEST _administration_rw_taxrate(void) strops::copy(pw.tax_sections[pw.tax_section_count++], "NL/1a", MAX_LEN_SHORT_DESC); count = administration::tax_rate_count(); - administration::tax_rate_add(pw); + administration::tax_rate_enable(pw); ASSERT_EQ(count+1, administration::tax_rate_count()); } diff --git a/tests/administration_validation_tests.cpp b/tests/administration_validation_tests.cpp index ab235c1..cd2aa0c 100644 --- a/tests/administration_validation_tests.cpp +++ b/tests/administration_validation_tests.cpp @@ -70,7 +70,7 @@ TEST _administration_validate_taxrate_add(void) administration::create_empty(""); tax_rate p1 = administration::tax_rate_create_empty(); - ASSERT_EQ(administration::tax_rate_add(p1), A_ERR_SUCCESS); + ASSERT_EQ(administration::tax_rate_enable(p1), A_ERR_SUCCESS); PASS(); } diff --git a/tests/test_helper.cpp b/tests/test_helper.cpp index ff20ff8..980fe8c 100644 --- a/tests/test_helper.cpp +++ b/tests/test_helper.cpp @@ -268,11 +268,11 @@ static void add_default_nl_tax_rates() u32 tr_count = country::get_available_tax_rates("NL", tr_buffer, 500); for (u32 i = 0; i < 10; i++) { - administration::tax_rate_add(tr_buffer[i]); + administration::tax_rate_enable(tr_buffer[i]); } for (u32 i = 0; i < 10; i++) { - administration::tax_rate_add(tr_buffer[tr_count - i - 1]); + administration::tax_rate_enable(tr_buffer[tr_count - i - 1]); } memops::unalloc(tr_buffer); } -- cgit v1.2.3-70-g09d2