diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/administration.cpp | 266 | ||||
| -rw-r--r-- | src/administration_writer.cpp | 6 | ||||
| -rw-r--r-- | src/locales/en.cpp | 2 | ||||
| -rw-r--r-- | src/ui/ui_earnings.cpp | 151 | ||||
| -rw-r--r-- | src/ui/ui_expenses.cpp | 2 | ||||
| -rw-r--r-- | src/ui/ui_invoices.cpp | 11 | ||||
| -rw-r--r-- | src/ui/ui_main.cpp | 8 |
7 files changed, 417 insertions, 29 deletions
diff --git a/src/administration.cpp b/src/administration.cpp index e6c9821..0cca2b7 100644 --- a/src/administration.cpp +++ b/src/administration.cpp @@ -1,3 +1,5 @@ +#define _CRT_SECURE_NO_WARNINGS + #include <string.h> #include <stdlib.h> #include <assert.h> @@ -33,12 +35,12 @@ static int compare_tax_countries(const void *a, const void *b) return strcmp(objA->country_code, objB->country_code); } -static invoice_status administation_get_random_invoice_status() +static invoice_status administration_get_random_invoice_status() { return (invoice_status)(rand() % invoice_status::INVOICE_END); } -static void administation_get_random_project(char* project_id) +static void administration_get_random_project(char* project_id) { int size = list_size(&g_administration.projects); if (size > 0) { @@ -48,7 +50,7 @@ static void administation_get_random_project(char* project_id) } } -static void administation_get_random_cost_center(char* cost_center_id) +static void administration_get_random_cost_center(char* cost_center_id) { int size = list_size(&g_administration.cost_centers); if (size > 0) { @@ -58,7 +60,7 @@ static void administation_get_random_cost_center(char* cost_center_id) } } -static contact* administation_get_random_contact() +static contact* administration_get_random_contact() { int size = list_size(&g_administration.contacts); if (size > 0) { @@ -76,7 +78,7 @@ static time_t administration_get_default_invoice_expire_duration() static void administration_recalculate_billing_item_totals(billing_item* item); -static void administation_get_random_billing_items(invoice* inv) +static void administration_get_random_billing_items(invoice* inv) { int amount = 1 + rand() % 20; @@ -364,22 +366,22 @@ static void administration_create_debug_data() #define ADD_INVOICE(_outgoing)\ {\ invoice inv = administration_invoice_create_empty();\ - if (_outgoing) inv.supplier = administration_company_info_get(); else inv.supplier = *administation_get_random_contact();\ - if (_outgoing) inv.customer = *administation_get_random_contact(); else inv.customer = administration_company_info_get();\ - administation_get_random_project(inv.project_id);\ - administation_get_random_cost_center(inv.cost_center_id);\ + if (_outgoing) inv.supplier = administration_company_info_get(); else inv.supplier = *administration_get_random_contact();\ + if (_outgoing) inv.customer = *administration_get_random_contact(); else inv.customer = administration_company_info_get();\ + administration_get_random_project(inv.project_id);\ + if (!_outgoing) administration_get_random_cost_center(inv.cost_center_id);\ inv.is_outgoing = _outgoing;\ - inv.status = administation_get_random_invoice_status();\ + inv.status = administration_get_random_invoice_status();\ inv.issued_at = time(NULL) - (86400 * (rand() % 720));\ inv.delivered_at = inv.issued_at;\ inv.expires_at = inv.issued_at + administration_get_default_invoice_expire_duration();\ - administation_get_random_billing_items(&inv);\ + administration_get_random_billing_items(&inv);\ administration_invoice_add(&inv);\ } // Create about 2 years of random data. - for (int i = 0; i < 1; i++) { ADD_INVOICE(1); } - for (int i = 0; i < 1; i++) { ADD_INVOICE(0); } + for (int i = 0; i < 200; i++) { ADD_INVOICE(1); } + for (int i = 0; i < 200; i++) { ADD_INVOICE(0); } } static s32 administration_create_sequence_number() @@ -407,7 +409,9 @@ void administration_create() administration_create_debug_data(); - administration_writer_save_all_async(); + //administration_writer_save_all_async(); + income_statement* statement = (income_statement*)malloc(sizeof(income_statement)); + administration_create_income_statement(statement); } static void administration_destroy_list(list_t *list) @@ -430,8 +434,194 @@ void administration_destroy() administration_destroy_list(&g_administration.cost_centers); } -// General functions. +// Other functions. // ======================= +static void time_t_to_quarter(time_t time, u16* year, u8* quarter) +{ + struct tm *lt = localtime(&time); + //sprinf(buffer, "%dQ%d", lt->tm_mon / 3, lt->tm_year / 100); + *year = (u16)((1900+lt->tm_year) % 100); + *quarter = (u8)(lt->tm_mon / 3); +} + +static void administration_debug_print_income_statement(income_statement* statement) +{ + for (u32 i = 0; i < statement->quarter_count; i++) + { + quarterly_report report = statement->quarters[i]; + + printf("=== %dQ%d ===\n", report.quarter+1, report.year); + printf("general revenue: %.2f\n", report.uncategorized_revenue); + printf("general taxes: %.2f\n", report.uncategorized_taxes); + printf("general expenses: %.2f\n", report.uncategorized_expenses); + + for (u32 x = 0; x < report.report_count; x++) + { + project_report pr = report.reports[x]; + + project proj; + administration_project_get_by_id(&proj, pr.project_id); + printf("PROJECT: %s\n", proj.description); + printf(" revenue: %.2f\n", pr.revenue); + printf(" taxes: %.2f\n", pr.taxes); + printf(" expenses: %.2f\n", pr.expenses_total); + + for (u32 y = 0; y < pr.expense_count; y++) + { + project_expense expense = pr.expenses[y]; + + cost_center costcenter; + administration_cost_center_get_by_id(&costcenter, expense.cost_center_id); + printf(" %s: %.2f\n", costcenter.code, expense.total); + } + } + + printf("\n"); + } +} + +void administration_create_income_statement(income_statement* statement) +{ + assert(statement); + statement->quarter_count = 0; + + u32 invoice_count = administration_invoice_count(); + invoice* invoice_buffer = (invoice*)malloc(sizeof(invoice)*invoice_count); + invoice_count = administration_invoice_get_all(invoice_buffer); + + // Find oldest and youngest invoice. + time_t oldest = INT64_MAX; + time_t youngest = 0; + for (u32 i = 0; i < invoice_count; i++) + { + if (invoice_buffer[i].delivered_at < oldest) oldest = invoice_buffer[i].delivered_at; + if (invoice_buffer[i].delivered_at > youngest) youngest = invoice_buffer[i].delivered_at; + } + + u16 oldest_year; + u8 oldest_quarter; + time_t_to_quarter(oldest, &oldest_year, &oldest_quarter); + + u16 youngest_year; + u8 youngest_quarter; + time_t_to_quarter(youngest, &youngest_year, &youngest_quarter); + + u32 num_quarters = (youngest_quarter+1 + (youngest_year*4)) - (oldest_quarter + (oldest_year*4)); + assert(num_quarters <= MAX_LEN_INCOME_STATEMENT_REPORT_QUARTERS); + + // Generate quarters. + for (u32 i = 0; i < num_quarters; i++) + { + quarterly_report quarter; + quarter.year = oldest_year + (u16)((oldest_quarter+i) / 4); + quarter.quarter = (u8)((oldest_quarter + (i)) % 4); + quarter.uncategorized_expenses = 0.0f; + quarter.uncategorized_revenue = 0.0f; + quarter.uncategorized_taxes = 0.0f; + quarter.report_count = 0; + snprintf(quarter.quarter_str, MAX_LEN_SHORT_DESC, "%dQ%d", quarter.quarter+1, quarter.year); + + u32 project_count = administration_project_count(); + project* project_buffer = (project*)malloc(sizeof(project)*project_count); + project_count = administration_project_get_all(project_buffer); + assert(project_count <= MAX_LEN_QUARTERLY_REPORT_PROJECTS); + + u32 costcenter_count = administration_cost_center_count(); + cost_center* costcenter_buffer = (cost_center*)malloc(sizeof(cost_center)*costcenter_count); + costcenter_count = administration_cost_center_get_all(costcenter_buffer); + assert(costcenter_count <= MAX_LEN_PROJECT_REPORT_COSTCENTERS); + + for (u32 x = 0; x < project_count; x++) + { + project_report report; + report.expenses_total = 0.0f; + report.revenue = 0.0f; + report.taxes = 0.0f; + report.expense_count = 0; + strops_copy(report.project_id, project_buffer[x].id, MAX_LEN_ID); + strops_copy(report.description, project_buffer[x].description, MAX_LEN_LONG_DESC); + + for (u32 y = 0; y < costcenter_count; y++) + { + project_expense expense; + strops_copy(expense.cost_center_id, costcenter_buffer[y].id, MAX_LEN_ID); + strops_copy(expense.description, costcenter_buffer[y].description, MAX_LEN_LONG_DESC); + expense.total = 0.0f; + report.expenses[report.expense_count++] = expense; + } + + quarter.reports[quarter.report_count++] = report; + } + + statement->quarters[statement->quarter_count++] = quarter; + } + + // Fill quarters. + for (u32 i = 0; i < invoice_count; i++) + { + invoice* inv = &invoice_buffer[i]; + + u16 yy; + u8 qq; + time_t_to_quarter(inv->delivered_at, &yy, &qq); + + u32 report_index = (qq + (yy*4)) - (oldest_quarter + (oldest_year*4)); + + quarterly_report* quarter = &statement->quarters[report_index]; + assert(yy == quarter->year && qq == quarter->quarter); + + if (strcmp(inv->project_id, "") == 0) { + if (inv->is_outgoing) { + quarter->uncategorized_revenue += inv->total; + quarter->uncategorized_taxes += inv->tax; + } + else { + quarter->uncategorized_expenses += inv->total; + } + } + else { + int project_report_index = -1; + for (u32 x = 0; x < quarter->report_count; x++) + { + if (strcmp(quarter->reports[x].project_id, inv->project_id) == 0) { + project_report_index = x; + break; + } + } + assert(project_report_index != -1); + + project_report* report = &quarter->reports[project_report_index]; + + if (inv->is_outgoing) { + report->revenue += inv->total; + report->taxes += inv->tax; + } + else { + report->expenses_total += inv->total; + + if (strcmp(inv->cost_center_id, "") != 0) { + int expense_report_index = -1; + for (u32 x = 0; x < report->expense_count; x++) + { + if (strcmp(report->expenses[x].cost_center_id, inv->cost_center_id) == 0) { + expense_report_index = x; + break; + } + } + assert(expense_report_index != -1); + + project_expense* expense = &report->expenses[expense_report_index]; + expense->total += inv->total; + } + } + } + } + + //administration_debug_print_income_statement(statement); + + free(invoice_buffer); +} + char* administration_file_path_get() { return g_administration.path; @@ -447,7 +637,7 @@ void administration_company_info_set(contact data) g_administration.company_info = data; } -administration* administation_get() +administration* administration_get() { return &g_administration; } @@ -635,6 +825,25 @@ u32 administration_project_count() return list_size(&g_administration.projects); } +bool administration_project_get_by_id(project* buffer, char* id) +{ + assert(buffer); + + list_iterator_start(&g_administration.projects); + while (list_iterator_hasnext(&g_administration.projects)) { + project c = *(project *)list_iterator_next(&g_administration.projects); + if (strcmp(c.id, id) == 0) + { + *buffer = c; + list_iterator_stop(&g_administration.projects); + return true; + } + } + list_iterator_stop(&g_administration.projects); + + return false; +} + u32 administration_project_get_all(project* buffer) { u32 write_cursor = 0; @@ -853,6 +1062,25 @@ u32 administration_cost_center_count() return list_size(&g_administration.cost_centers); } +bool administration_cost_center_get_by_id(cost_center* buffer, char* id) +{ + assert(buffer); + + list_iterator_start(&g_administration.cost_centers); + while (list_iterator_hasnext(&g_administration.cost_centers)) { + cost_center c = *(cost_center *)list_iterator_next(&g_administration.cost_centers); + if (strcmp(c.id, id) == 0) + { + *buffer = c; + list_iterator_stop(&g_administration.cost_centers); + return true; + } + } + list_iterator_stop(&g_administration.cost_centers); + + return false; +} + u32 administration_cost_center_get_all(cost_center* buffer) { assert(buffer); @@ -1059,7 +1287,7 @@ bool administration_invoice_remove(invoice* inv) static void administration_invoice_set_refs(invoice* inv) { // This function makes sure that contact info referenced in the IDs actually - // matches the contact info stored in administation, if not we make new contacts. + // matches the contact info stored in administration, if not we make new contacts. // Check if supplier info is equal to contact stored in supplier id, in case we autocomplete and edit data after, // this should be handled as a new contact. @@ -1203,12 +1431,12 @@ u32 administration_invoice_count() return list_size(&g_administration.invoices); } -u32 administation_invoice_get_incomming_count() +u32 administration_invoice_get_incomming_count() { return g_administration.expense_count; } -u32 administation_invoice_get_outgoing_count() +u32 administration_invoice_get_outgoing_count() { return g_administration.invoice_count; } diff --git a/src/administration_writer.cpp b/src/administration_writer.cpp index 0176d97..d9c9c31 100644 --- a/src/administration_writer.cpp +++ b/src/administration_writer.cpp @@ -527,9 +527,9 @@ bool administration_writer_save_all_administration_info_blocking() int buf_length = 0; char* file_content = administration_writer_copy_template(administration_save_template, &buf_length); - strops_replace_int32(file_content, buf_length, "{{NEXT_ID}}", administation_get()->next_id); - strops_replace_int32(file_content, buf_length, "{{NEXT_SEQUENCE_NUMBER}}", administation_get()->next_sequence_number); - strops_replace(file_content, buf_length, "{{PROGRAM_VERSION}}", administation_get()->program_version); + strops_replace_int32(file_content, buf_length, "{{NEXT_ID}}", administration_get()->next_id); + strops_replace_int32(file_content, buf_length, "{{NEXT_SEQUENCE_NUMBER}}", administration_get()->next_sequence_number); + strops_replace(file_content, buf_length, "{{PROGRAM_VERSION}}", administration_get()->program_version); //// Write to Disk. int final_length = (int)strlen(file_content); diff --git a/src/locales/en.cpp b/src/locales/en.cpp index 03e5940..6013f84 100644 --- a/src/locales/en.cpp +++ b/src/locales/en.cpp @@ -79,7 +79,7 @@ locale_entry en_locales[] = { {"nav.expenses", "Expenses"}, {"nav.contacts", "Contacts"}, {"nav.reports", "Reports"}, - {"nav.reports.results", "Results"}, + {"nav.reports.results", "Earnings"}, {"nav.reports.tax", "Tax return"}, {"nav.projects", "Projects"}, {"nav.settings", "Settings"}, diff --git a/src/ui/ui_earnings.cpp b/src/ui/ui_earnings.cpp new file mode 100644 index 0000000..81e31b5 --- /dev/null +++ b/src/ui/ui_earnings.cpp @@ -0,0 +1,151 @@ +#include <stdio.h> +#include <stdlib.h> + +#include "ui.hpp" +#include "imgui.h" +#include "administration.hpp" +#include "locales.hpp" + +income_statement* statement = 0; + +void ui_setup_earnings() +{ + statement = (income_statement*)malloc(sizeof(income_statement)); + administration_create_income_statement(statement); +} + +void ui_destroy_earnings() +{ + free(statement); +} + +void ui_draw_earnings() +{ + if (ImGui::BeginTable("QuarterlyResultsTable", 5, + ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit)) + { + ImGui::TableSetupColumn("##names"); + + int quarter_start = 0; + int quarter_count = 4; + + // Table header + for (int q = 0; q < quarter_count; q++) + { + ImGui::TableSetupColumn(statement->quarters[q].quarter_str, ImGuiTableColumnFlags_WidthStretch); + } + + ImGui::TableHeadersRow(); + + // Uncategorized income and expenses + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); ImGui::Text("(Uncategorized)"); + ImGui::TableSetColumnIndex(1); ImGui::Text(""); + ImGui::TableSetColumnIndex(2); ImGui::Text(""); + ImGui::TableSetColumnIndex(3); ImGui::Text(""); + ImGui::TableSetColumnIndex(4); ImGui::Text(""); + + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); ImGui::TextUnformatted(" Revenue"); + ImGui::TableSetColumnIndex(1); ImGui::Text("%.2f", statement->quarters[quarter_start + 0].uncategorized_revenue); + ImGui::TableSetColumnIndex(2); ImGui::Text("%.2f", statement->quarters[quarter_start + 1].uncategorized_revenue); + ImGui::TableSetColumnIndex(3); ImGui::Text("%.2f", statement->quarters[quarter_start + 2].uncategorized_revenue); + ImGui::TableSetColumnIndex(4); ImGui::Text("%.2f", statement->quarters[quarter_start + 3].uncategorized_revenue); + + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); ImGui::TextUnformatted(" Tax"); + ImGui::TableSetColumnIndex(1); ImGui::Text("%.2f", statement->quarters[quarter_start + 0].uncategorized_taxes); + ImGui::TableSetColumnIndex(2); ImGui::Text("%.2f", statement->quarters[quarter_start + 1].uncategorized_taxes); + ImGui::TableSetColumnIndex(3); ImGui::Text("%.2f", statement->quarters[quarter_start + 2].uncategorized_taxes); + ImGui::TableSetColumnIndex(4); ImGui::Text("%.2f", statement->quarters[quarter_start + 3].uncategorized_taxes); + + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); ImGui::TextUnformatted(" Expenses"); + ImGui::TableSetColumnIndex(1); ImGui::Text("%.2f", statement->quarters[quarter_start + 0].uncategorized_expenses); + ImGui::TableSetColumnIndex(2); ImGui::Text("%.2f", statement->quarters[quarter_start + 1].uncategorized_expenses); + ImGui::TableSetColumnIndex(3); ImGui::Text("%.2f", statement->quarters[quarter_start + 2].uncategorized_expenses); + ImGui::TableSetColumnIndex(4); ImGui::Text("%.2f", statement->quarters[quarter_start + 3].uncategorized_expenses); + + quarterly_report default_quater = statement->quarters[0]; + for (u32 p = 0; p < default_quater.report_count; p++) + { + ImGui::TableNextRow(); + project_report* report = &default_quater.reports[p]; + ImGui::TableSetColumnIndex(0); ImGui::Text("(%s)", report->description); + ImGui::TableSetColumnIndex(1); ImGui::Text(""); + ImGui::TableSetColumnIndex(2); ImGui::Text(""); + ImGui::TableSetColumnIndex(3); ImGui::Text(""); + ImGui::TableSetColumnIndex(4); ImGui::Text(""); + + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); ImGui::TextUnformatted(" Revenue"); + ImGui::TableSetColumnIndex(1); ImGui::Text("%.2f", statement->quarters[quarter_start + 0].reports[p].revenue); + ImGui::TableSetColumnIndex(2); ImGui::Text("%.2f", statement->quarters[quarter_start + 1].reports[p].revenue); + ImGui::TableSetColumnIndex(3); ImGui::Text("%.2f", statement->quarters[quarter_start + 2].reports[p].revenue); + ImGui::TableSetColumnIndex(4); ImGui::Text("%.2f", statement->quarters[quarter_start + 3].reports[p].revenue); + + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); ImGui::TextUnformatted(" Tax"); + ImGui::TableSetColumnIndex(1); ImGui::Text("%.2f", statement->quarters[quarter_start + 0].reports[p].taxes); + ImGui::TableSetColumnIndex(2); ImGui::Text("%.2f", statement->quarters[quarter_start + 1].reports[p].taxes); + ImGui::TableSetColumnIndex(3); ImGui::Text("%.2f", statement->quarters[quarter_start + 2].reports[p].taxes); + ImGui::TableSetColumnIndex(4); ImGui::Text("%.2f", statement->quarters[quarter_start + 3].reports[p].taxes); + + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); ImGui::TextUnformatted(" Expenses"); + ImGui::TableSetColumnIndex(1); ImGui::Text("%.2f", statement->quarters[quarter_start + 0].reports[p].expenses_total); + ImGui::TableSetColumnIndex(2); ImGui::Text("%.2f", statement->quarters[quarter_start + 1].reports[p].expenses_total); + ImGui::TableSetColumnIndex(3); ImGui::Text("%.2f", statement->quarters[quarter_start + 2].reports[p].expenses_total); + ImGui::TableSetColumnIndex(4); ImGui::Text("%.2f", statement->quarters[quarter_start + 3].reports[p].expenses_total); + + for (u32 e = 0; e < report->expense_count; e++) + { + ImGui::TableNextRow(); + project_expense* expense = &report->expenses[e]; + ImGui::TableSetColumnIndex(0); ImGui::Text(" %s", localize(expense->description)); + ImGui::TableSetColumnIndex(1); ImGui::Text("%.2f", statement->quarters[quarter_start + 0].reports[p].expenses[e].total); + ImGui::TableSetColumnIndex(2); ImGui::Text("%.2f", statement->quarters[quarter_start + 1].reports[p].expenses[e].total); + ImGui::TableSetColumnIndex(3); ImGui::Text("%.2f", statement->quarters[quarter_start + 2].reports[p].expenses[e].total); + ImGui::TableSetColumnIndex(4); ImGui::Text("%.2f", statement->quarters[quarter_start + 3].reports[p].expenses[e].total); + + + } + } + + /* + for (int i = 0; i < 1; i++) + { + quarterly_report quarter = statement->quarters[quarter_start + quarter_index]; + + for (u32 p = 0; p < quarter.report_count; p++) + { + ImGui::TableNextRow(); + project_report* report = &quarter.reports[p]; + ImGui::TableSetColumnIndex(0); ImGui::TextUnformatted(report->description); + ImGui::TableSetColumnIndex(1); ImGui::Text(""); + ImGui::TableSetColumnIndex(2); ImGui::Text(""); + ImGui::TableSetColumnIndex(3); ImGui::Text(""); + ImGui::TableSetColumnIndex(4); ImGui::Text(""); + + + // for (u32 e = 0; e < report->expense_count; e++) + // { + // project_expense* expense = &report->expenses[e]; + // ImGui::TableNextColumn(); ImGui::TextUnformatted(expense->description); + // } + } + }*/ + + // // Rows + // for (int i = 0; i < results_count; i++) + // { + // ImGui::TableNextRow(); + // ImGui::TableSetColumnIndex(0); ImGui::TextUnformatted(results[i].quarter); + // ImGui::TableSetColumnIndex(1); ImGui::TextUnformatted(results[i].revenue); + // ImGui::TableSetColumnIndex(2); ImGui::TextUnformatted(results[i].profit); + // ImGui::TableSetColumnIndex(3); ImGui::TextUnformatted(results[i].expenses); + // } + + ImGui::EndTable(); + } +}
\ No newline at end of file diff --git a/src/ui/ui_expenses.cpp b/src/ui/ui_expenses.cpp index 6d1b36c..ab47e26 100644 --- a/src/ui/ui_expenses.cpp +++ b/src/ui/ui_expenses.cpp @@ -343,7 +343,7 @@ static void ui_draw_expenses_list() invoice invoice_list[items_per_page]; u32 invoice_count = administration_invoice_get_partial_list_incomming(current_page, items_per_page, invoice_list); - u32 total_invoice_count = administation_invoice_get_incomming_count(); + u32 total_invoice_count = administration_invoice_get_incomming_count(); s32 max_page = (total_invoice_count + items_per_page - 1) / items_per_page; if (max_page == 0) max_page = 1; diff --git a/src/ui/ui_invoices.cpp b/src/ui/ui_invoices.cpp index 8cdf959..9d6f8a2 100644 --- a/src/ui/ui_invoices.cpp +++ b/src/ui/ui_invoices.cpp @@ -18,14 +18,17 @@ static invoice selected_for_removal = {0}; static country_tax_bracket* tax_bracket_list_buffer = 0; static billing_item* invoice_items_buffer = 0; +static project* project_list_buffer = 0; void ui_draw_address_form(address* buffer); void draw_contact_form_ex(contact* buffer, bool viewing_only = false, bool with_autocomplete = false, bool* on_autocomplete = 0); +void draw_project_selector(char* project_id, project* buffer); void ui_destroy_invoices() { free(tax_bracket_list_buffer); free(invoice_items_buffer); + free(project_list_buffer); } void ui_setup_invoices() @@ -38,6 +41,9 @@ void ui_setup_invoices() u32 invoice_items_count = MAX_BILLING_ITEMS; invoice_items_buffer = (billing_item*)malloc(sizeof(billing_item) * invoice_items_count); + + u32 project_count = administration_project_count(); + project_list_buffer = (project*) malloc(sizeof(project) * project_count); } void draw_tax_bracket_selector(char* tax_bracket_id, country_tax_bracket* buffer, char* country_code) @@ -328,6 +334,9 @@ static void draw_invoice_form(invoice* buffer, bool viewing_only = false) } ImGui::Separator(); + // 9. Project selection + draw_project_selector(buffer->project_id, project_list_buffer); + ImGui::Spacing(); ImGui::Spacing(); ImGui::Spacing(); @@ -364,7 +373,7 @@ static void ui_draw_invoices_list() invoice invoice_list[items_per_page]; u32 invoice_count = administration_invoice_get_partial_list_outgoing(current_page, items_per_page, invoice_list); - u32 total_invoice_count = administation_invoice_get_outgoing_count(); + u32 total_invoice_count = administration_invoice_get_outgoing_count(); s32 max_page = (total_invoice_count + items_per_page - 1) / items_per_page; if (max_page == 0) max_page = 1; diff --git a/src/ui/ui_main.cpp b/src/ui/ui_main.cpp index 33747f1..9ff965d 100644 --- a/src/ui/ui_main.cpp +++ b/src/ui/ui_main.cpp @@ -21,7 +21,7 @@ void (*drawcalls[dashboard_view_state::END])(void) = { ui_draw_invoices, ui_draw_expenses, ui_draw_contacts, - 0, + ui_draw_earnings, 0, ui_draw_projects, ui_draw_settings, @@ -31,7 +31,7 @@ void (*setupcalls[dashboard_view_state::END])(void) = { ui_setup_invoices, ui_setup_expenses, ui_setup_contacts, - 0, + ui_setup_earnings, 0, ui_setup_projects, ui_setup_settings, @@ -41,7 +41,7 @@ void (*destroycalls[dashboard_view_state::END])(void) = { ui_destroy_invoices, ui_destroy_expenses, 0, - 0, + ui_destroy_earnings, 0, 0, ui_destroy_settings, @@ -94,7 +94,7 @@ void ui_draw_main() if (ImGui::Button(localize("nav.expenses"), ImVec2(buttonWidth, 24))) set_dashboard_state(dashboard_view_state::EXPENSES); if (ImGui::Button(localize("nav.contacts"), ImVec2(buttonWidth, 24))) set_dashboard_state(dashboard_view_state::CONTACTS); - static bool reports_opened = false; + static bool reports_opened = true; if (ImGui::Button(localize("nav.reports"), ImVec2(buttonWidth, 24))) reports_opened = !reports_opened; if (reports_opened) { |
