From 543aa7d53136037f07302a5653bba90751ac1552 Mon Sep 17 00:00:00 2001 From: Aldrik Ramaekers Date: Sat, 16 Aug 2025 20:24:28 +0200 Subject: more refactors --- src/administration.cpp | 468 ++++++++++++++++++++++++++++--------------------- 1 file changed, 272 insertions(+), 196 deletions(-) (limited to 'src/administration.cpp') diff --git a/src/administration.cpp b/src/administration.cpp index 4d8233e..ace1383 100644 --- a/src/administration.cpp +++ b/src/administration.cpp @@ -264,14 +264,29 @@ static void administration_create_debug_data() ADD_PROJECT("Kayak rental"); // Company info. + + snprintf(g_administration.company_info.id, sizeof(g_administration.company_info.id), "C/%d", administration_create_id()); strops_copy(g_administration.company_info.name, "Aldrik Ramaekers", sizeof(g_administration.company_info.name)); strops_copy(g_administration.company_info.address.address1, "Keerderstraat 81", sizeof(g_administration.company_info.address.address1)); strops_copy(g_administration.company_info.address.address2, "6226XW Maastricht", sizeof(g_administration.company_info.address.address2)); strops_copy(g_administration.company_info.address.country_code, "NL", sizeof(g_administration.company_info.address.country_code)); strops_copy(g_administration.company_info.taxid, "123", sizeof(g_administration.company_info.taxid)); strops_copy(g_administration.company_info.businessid, "123", sizeof(g_administration.company_info.businessid)); + g_administration.next_id++; +} + +static s32 administration_create_sequence_number() +{ + return g_administration.next_sequence_number; } +static time_t administration_get_default_invoice_expire_duration() +{ + return (30 * 24 * 60 * 60); // 30 days +} + +// Setup functions. +// ======================= void administration_create() { g_administration.next_id = 1; @@ -284,23 +299,50 @@ void administration_create() list_init(&g_administration.cost_centers); strops_copy(g_administration.path, "", sizeof(g_administration.path)); - snprintf(g_administration.company_info.id, sizeof(g_administration.company_info.id), "C/%d", administration_create_id()); - g_administration.next_id++; - administration_create_default_tax_brackets(); administration_create_default_cost_centers(); administration_create_debug_data(); } +static void administration_destroy_list(list_t *list) +{ + list_iterator_start(list); + while (list_iterator_hasnext(list)) { + void* c = (void *)list_iterator_next(list); + free(c); + } + list_iterator_stop(list); + list_destroy(list); +} + void administration_destroy() { - list_destroy(&g_administration.invoices); - list_destroy(&g_administration.contacts); - list_destroy(&g_administration.projects); - list_destroy(&g_administration.tax_brackets); - list_destroy(&g_administration.cost_centers); + administration_destroy_list(&g_administration.invoices); + administration_destroy_list(&g_administration.contacts); + administration_destroy_list(&g_administration.projects); + administration_destroy_list(&g_administration.tax_brackets); + administration_destroy_list(&g_administration.cost_centers); } +// General functions. +// ======================= +char* administration_file_path_get() +{ + return g_administration.path; +} + +contact administration_company_info_get() +{ + return g_administration.company_info; +} + +void administration_company_info_set(contact data) +{ + g_administration.company_info = data; +} + +// Contact functions. +// ======================= bool administration_contact_add(contact data) { if (!administration_contact_is_valid(data)) return false; @@ -349,6 +391,7 @@ bool administration_contact_remove(contact data) if (strcmp(c->id, data.id) == 0) { list_iterator_stop(&g_administration.contacts); list_delete(&g_administration.contacts, c); + free(c); return true; } } @@ -384,6 +427,24 @@ u32 administration_contact_get_partial_list(u32 page_index, u32 page_size, conta return write_cursor; } +bool administration_contact_get_by_id(contact* buffer, char* id) +{ + bool result = false; + list_iterator_start(&g_administration.contacts); + while (list_iterator_hasnext(&g_administration.contacts)) { + contact c = *(contact *)list_iterator_next(&g_administration.contacts); + + if (strcmp(c.id, id) == 0) { + list_iterator_stop(&g_administration.projects); + *buffer = c; + result = true; + } + } + list_iterator_stop(&g_administration.contacts); + + return result; +} + int administration_contact_get_autocompletions(contact* buffer, int buf_size, char* name) { int write_cursor = 0; @@ -403,33 +464,39 @@ int administration_contact_get_autocompletions(contact* buffer, int buf_size, ch return write_cursor; } -char* administration_file_path_get() +bool administration_contact_is_valid(contact data) { - return g_administration.path; + if (data.type == contact_type::CONTACT_CONSUMER) + { + return strlen(data.name) > 0 && strlen(data.address.address1) > 0 && strlen(data.address.address2) > 0 && strlen(data.address.country_code) > 0; + } + else if (data.type == contact_type::CONTACT_BUSINESS) + { + return strlen(data.name) > 0 && strlen(data.address.address1) > 0 && strlen(data.address.address2) > 0 && strlen(data.address.country_code) > 0 + && strlen(data.taxid) > 0 && strlen(data.businessid); + } + + return false; } -u32 administration_project_count() +contact administration_contact_create_empty() { - return list_size(&g_administration.projects); + contact result; + memset(&result, 0, sizeof(contact)); + snprintf(result.id, sizeof(result.id), "C/%d", administration_create_id()); + return result; } -u32 administration_billing_items_count(invoice* invoice) +bool administration_contact_equals(contact c1, contact c2) { - return list_size(&invoice->billing_items); + return memcmp(&c1, &c2, sizeof(contact)) == 0; } -u32 administration_billing_item_get_all_for_invoice(invoice* invoice, billing_item* buffer) +// Project functions. +// ======================= +u32 administration_project_count() { - u32 write_cursor = 0; - - list_iterator_start(&invoice->billing_items); - while (list_iterator_hasnext(&invoice->billing_items)) { - billing_item c = *(billing_item *)list_iterator_next(&invoice->billing_items); - buffer[write_cursor++] = c; - } - list_iterator_stop(&invoice->billing_items); - - return write_cursor; + return list_size(&g_administration.projects); } u32 administration_project_get_all(project* buffer) @@ -480,23 +547,6 @@ bool administration_project_is_valid(project data) return strlen(data.description) > 0; } -char* administration_invoice_get_status_string(invoice* invoice) -{ - switch(invoice->status) - { - case invoice_status::INVOICE_CONCEPT: return "invoice.state.concept"; - case invoice_status::INVOICE_SENT: return "invoice.state.sent"; - case invoice_status::INVOICE_REMINDED: return "invoice.state.reminded"; - case invoice_status::INVOICE_PAID: return "invoice.state.paid"; - case invoice_status::INVOICE_EXPIRED: return "invoice.state.expired"; - case invoice_status::INVOICE_CANCELLED: return "invoice.state.cancelled"; - case invoice_status::INVOICE_REFUNDED: return "invoice.state.refunded"; - case invoice_status::INVOICE_CORRECTED: return "invoice.state.corrected"; - default: assert(0); break; - } - return ""; -} - char* administration_project_get_status_string(project data) { switch(data.state) @@ -553,6 +603,7 @@ bool administration_project_remove(project data) if (strcmp(c->id, data.id) == 0) { list_iterator_stop(&g_administration.projects); list_delete(&g_administration.projects, c); + free(c); return true; } } @@ -561,14 +612,33 @@ bool administration_project_remove(project data) return false; } -contact administration_company_info_get() +project administration_project_create_empty() { - return g_administration.company_info; + project result; + memset(&result, 0, sizeof(project)); + snprintf(result.id, sizeof(result.id), "P/%d", administration_create_id()); + return result; } -void administration_company_info_set(contact data) +// Tax bracket functions. +// ======================= +static bool administration_get_tax_bracket_by_id(country_tax_bracket* buffer, char* id) { - g_administration.company_info = data; + assert(buffer); + + list_iterator_start(&g_administration.tax_brackets); + while (list_iterator_hasnext(&g_administration.tax_brackets)) { + country_tax_bracket c = *(country_tax_bracket *)list_iterator_next(&g_administration.tax_brackets); + if (strcmp(c.id, id) == 0) + { + *buffer = c; + list_iterator_stop(&g_administration.tax_brackets); + return true; + } + } + list_iterator_stop(&g_administration.tax_brackets); + + return false; } u32 administration_tax_bracket_count() @@ -634,6 +704,8 @@ bool administration_tax_bracket_update(country_tax_bracket data) return false; } +// Cost center functions. +// ======================= u32 administration_cost_center_count() { return list_size(&g_administration.cost_centers); @@ -720,52 +792,8 @@ bool administration_cost_center_update(cost_center data) return false; } -bool administration_contact_is_valid(contact data) -{ - if (data.type == contact_type::CONTACT_CONSUMER) - { - return strlen(data.name) > 0 && strlen(data.address.address1) > 0 && strlen(data.address.address2) > 0 && strlen(data.address.country_code) > 0; - } - else if (data.type == contact_type::CONTACT_BUSINESS) - { - return strlen(data.name) > 0 && strlen(data.address.address1) > 0 && strlen(data.address.address2) > 0 && strlen(data.address.country_code) > 0 - && strlen(data.taxid) > 0 && strlen(data.businessid); - } - - return false; -} - -static s32 administration_create_sequence_number() -{ - return g_administration.next_sequence_number; -} - -static time_t administration_get_default_invoice_expire_duration() -{ - return (30 * 24 * 60 * 60); // 30 days -} - -billing_item administration_billing_item_create_empty() -{ - billing_item item; - memset(&item, 0, sizeof(billing_item)); - item.amount = 1; - return item; -} - -bool administration_billing_item_add_to_invoice(invoice* invoice, billing_item item) -{ - billing_item* tb = (billing_item*)malloc(sizeof(billing_item)); - memcpy(tb, &item, sizeof(billing_item)); - snprintf(tb->id, sizeof(tb->id), "B/%d", administration_create_id()); - strops_copy(tb->invoice_id, invoice->id, sizeof(tb->invoice_id)); - list_append(&invoice->billing_items, tb); - strops_copy(tb->currency, invoice->currency, MAX_LEN_CURRENCY); // Set billing item currency to invoice currency. - - g_administration.next_id++; - - return true; -} +// Invoice functions. +// ======================= static char* administration_get_default_currency_for_country(char* country_code) { @@ -821,41 +849,6 @@ invoice administration_invoice_create_empty() return result; } -contact administration_contact_create_empty() -{ - contact result; - memset(&result, 0, sizeof(contact)); - snprintf(result.id, sizeof(result.id), "C/%d", administration_create_id()); - return result; -} - -project administration_project_create_empty() -{ - project result; - memset(&result, 0, sizeof(project)); - snprintf(result.id, sizeof(result.id), "P/%d", administration_create_id()); - return result; -} - -static bool administration_get_tax_bracket_by_id(country_tax_bracket* buffer, char* id) -{ - assert(buffer); - - list_iterator_start(&g_administration.tax_brackets); - while (list_iterator_hasnext(&g_administration.tax_brackets)) { - country_tax_bracket c = *(country_tax_bracket *)list_iterator_next(&g_administration.tax_brackets); - if (strcmp(c.id, id) == 0) - { - *buffer = c; - list_iterator_stop(&g_administration.tax_brackets); - return true; - } - } - list_iterator_stop(&g_administration.tax_brackets); - - return false; -} - static void administration_recalculate_invoice_totals(invoice* invoice) { invoice->tax = 0.0f; @@ -873,75 +866,6 @@ static void administration_recalculate_invoice_totals(invoice* invoice) list_iterator_stop(&invoice->billing_items); } -static void administration_recalculate_billing_item_totals(billing_item* item) -{ - if (item->amount_is_percentage) - { - item->net = item->net_per_item * (item->amount / 100.0f); - } - else - { - item->net = item->net_per_item * item->amount; - } - - if (item->discount != 0) - { - if (item->discount_is_percentage) - { - item->net -= item->net * (item->discount / 100.0f); - } - else - { - item->net -= item->discount; - } - } - - country_tax_bracket bracket; - if (administration_get_tax_bracket_by_id(&bracket, item->tax_bracket_id)) - { - item->tax = item->net * (bracket.rate/100.0f); - } - - item->total = item->net + item->tax; -} - -bool administration_billing_item_remove_from_invoice(invoice* invoice, billing_item item) -{ - list_iterator_start(&invoice->billing_items); - while (list_iterator_hasnext(&invoice->billing_items)) { - billing_item* c = (billing_item *)list_iterator_next(&invoice->billing_items); - - if (strcmp(c->id, item.id) == 0) { - list_iterator_stop(&invoice->billing_items); - list_delete(&invoice->billing_items, c); - return true; - } - } - list_iterator_stop(&invoice->billing_items); - - return false; -} - -bool administration_billing_item_update_in_invoice(invoice* invoice, billing_item item) -{ - list_iterator_start(&invoice->billing_items); - while (list_iterator_hasnext(&invoice->billing_items)) { - billing_item* c = (billing_item *)list_iterator_next(&invoice->billing_items); - - if (strcmp(c->id, item.id) == 0) { - memcpy(c, &item, sizeof(billing_item)); - list_iterator_stop(&invoice->billing_items); - - administration_recalculate_billing_item_totals(c); - administration_recalculate_invoice_totals(invoice); - return true; - } - } - list_iterator_stop(&invoice->billing_items); - - return false; -} - void administration_invoice_set_currency(invoice* invoice, char* currency) { strops_copy(invoice->currency, currency, MAX_LEN_CURRENCY); @@ -965,6 +889,25 @@ bool administration_invoice_is_valid(invoice* invoice) return true; } +bool administration_invoice_remove(invoice* inv) +{ + list_iterator_start(&g_administration.invoices); + while (list_iterator_hasnext(&g_administration.invoices)) { + invoice* c = (invoice *)list_iterator_next(&g_administration.invoices); + + if (strcmp(c->id, inv->id) == 0) + { + list_iterator_stop(&g_administration.invoices); + administration_destroy_list(&c->billing_items); + list_delete(&g_administration.invoices, c); + free(c); + return true; + } + } + list_iterator_stop(&g_administration.invoices); + return false; +} + bool administration_invoice_update(invoice* inv) { if (!administration_invoice_is_valid(inv)) return false; @@ -1084,4 +1027,137 @@ u32 administration_invoice_get_partial_list(u32 page_index, u32 page_size, invoi list_iterator_stop(&g_administration.invoices); return write_cursor; +} + +char* administration_invoice_get_status_string(invoice* invoice) +{ + switch(invoice->status) + { + case invoice_status::INVOICE_CONCEPT: return "invoice.state.concept"; + case invoice_status::INVOICE_SENT: return "invoice.state.sent"; + case invoice_status::INVOICE_REMINDED: return "invoice.state.reminded"; + case invoice_status::INVOICE_PAID: return "invoice.state.paid"; + case invoice_status::INVOICE_EXPIRED: return "invoice.state.expired"; + case invoice_status::INVOICE_CANCELLED: return "invoice.state.cancelled"; + case invoice_status::INVOICE_REFUNDED: return "invoice.state.refunded"; + case invoice_status::INVOICE_CORRECTED: return "invoice.state.corrected"; + default: assert(0); break; + } + return ""; +} + +// Billing item functions. +// ======================= + +static void administration_recalculate_billing_item_totals(billing_item* item) +{ + if (item->amount_is_percentage) + { + item->net = item->net_per_item * (item->amount / 100.0f); + } + else + { + item->net = item->net_per_item * item->amount; + } + + if (item->discount != 0) + { + if (item->discount_is_percentage) + { + item->net -= item->net * (item->discount / 100.0f); + } + else + { + item->net -= item->discount; + } + } + + country_tax_bracket bracket; + if (administration_get_tax_bracket_by_id(&bracket, item->tax_bracket_id)) + { + item->tax = item->net * (bracket.rate/100.0f); + } + + item->total = item->net + item->tax; +} + +u32 administration_billing_item_count(invoice* invoice) +{ + return list_size(&invoice->billing_items); +} + +u32 administration_billing_item_get_all_for_invoice(invoice* invoice, billing_item* buffer) +{ + u32 write_cursor = 0; + + list_iterator_start(&invoice->billing_items); + while (list_iterator_hasnext(&invoice->billing_items)) { + billing_item c = *(billing_item *)list_iterator_next(&invoice->billing_items); + buffer[write_cursor++] = c; + } + list_iterator_stop(&invoice->billing_items); + + return write_cursor; +} + +bool administration_billing_item_remove_from_invoice(invoice* invoice, billing_item item) +{ + list_iterator_start(&invoice->billing_items); + while (list_iterator_hasnext(&invoice->billing_items)) { + billing_item* c = (billing_item *)list_iterator_next(&invoice->billing_items); + + if (strcmp(c->id, item.id) == 0) { + list_iterator_stop(&invoice->billing_items); + list_delete(&invoice->billing_items, c); + free(c); + return true; + } + } + list_iterator_stop(&invoice->billing_items); + + return false; +} + +bool administration_billing_item_update_in_invoice(invoice* invoice, billing_item item) +{ + list_iterator_start(&invoice->billing_items); + while (list_iterator_hasnext(&invoice->billing_items)) { + billing_item* c = (billing_item *)list_iterator_next(&invoice->billing_items); + + if (strcmp(c->id, item.id) == 0) { + memcpy(c, &item, sizeof(billing_item)); + list_iterator_stop(&invoice->billing_items); + + administration_recalculate_billing_item_totals(c); + administration_recalculate_invoice_totals(invoice); + return true; + } + } + list_iterator_stop(&invoice->billing_items); + + return false; +} + +bool administration_billing_item_add_to_invoice(invoice* invoice, billing_item item) +{ + if (administration_billing_item_count(invoice) >= MAX_BILLING_ITEMS) return false; + + billing_item* tb = (billing_item*)malloc(sizeof(billing_item)); + memcpy(tb, &item, sizeof(billing_item)); + snprintf(tb->id, sizeof(tb->id), "B/%d", administration_create_id()); + strops_copy(tb->invoice_id, invoice->id, sizeof(tb->invoice_id)); + list_append(&invoice->billing_items, tb); + strops_copy(tb->currency, invoice->currency, MAX_LEN_CURRENCY); // Set billing item currency to invoice currency. + + g_administration.next_id++; + + return true; +} + +billing_item administration_billing_item_create_empty() +{ + billing_item item; + memset(&item, 0, sizeof(billing_item)); + item.amount = 1; + return item; } \ No newline at end of file -- cgit v1.2.3-70-g09d2