/* * Copyright (c) 2025 Aldrik Ramaekers * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #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() { static s32 current_page = 0; s32 max_page = ((statement->quarter_count) / 4); if (current_page >= max_page-1) current_page = max_page-1; if (current_page < 0) current_page = 0; bool enable_prev = current_page > 0; if (!enable_prev) ImGui::BeginDisabled(); if (ImGui::Button(locale::get("ui.prev")) && current_page > 0) current_page--; if (!enable_prev) ImGui::EndDisabled(); ImGui::SameLine(); ImGui::Text("(%d/%d)", current_page+1, max_page); ImGui::SameLine(); bool enable_next = current_page < max_page-1; if (!enable_next) ImGui::BeginDisabled(); if (ImGui::Button(locale::get("ui.next")) && current_page < max_page-1) current_page++; if (!enable_next) ImGui::EndDisabled(); ImGui::Spacing(); char* currency_symbol = administration_get_currency_symbol_for_currency(administration_get_default_currency()); if (ImGui::BeginTable("QuarterlyResultsTable", 5, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg | ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Hideable)) { ImGui::TableSetupColumn("##names", ImGuiTableColumnFlags_WidthFixed, 300); int quarter_count = 4; int quarter_start = current_page*quarter_count; ImGui::PushFont(fontBold); for (int q = 0; q < quarter_count; q++) { ImGui::TableSetupColumn(statement->quarters[quarter_start+q].quarter_str, ImGuiTableColumnFlags_WidthStretch); } if (statement->quarters[quarter_start].is_empty) ImGui::TableSetColumnEnabled(1, false); else ImGui::TableSetColumnEnabled(1, true); if (statement->quarters[quarter_start+1].is_empty) ImGui::TableSetColumnEnabled(2, false); else ImGui::TableSetColumnEnabled(2, true); if (statement->quarters[quarter_start+2].is_empty) ImGui::TableSetColumnEnabled(3, false); else ImGui::TableSetColumnEnabled(3, true); if (statement->quarters[quarter_start+3].is_empty) ImGui::TableSetColumnEnabled(4, false); else ImGui::TableSetColumnEnabled(4, true); ImGui::TableHeadersRow(); ImGui::PopFont(); bool has_uncategorized_revenue = (statement->quarters[quarter_start + 0].uncategorized_revenue + statement->quarters[quarter_start + 1].uncategorized_revenue + statement->quarters[quarter_start + 2].uncategorized_revenue + statement->quarters[quarter_start + 3].uncategorized_revenue) != 0.0f; bool has_uncategorized_taxes = (statement->quarters[quarter_start + 0].uncategorized_taxes + statement->quarters[quarter_start + 1].uncategorized_taxes + statement->quarters[quarter_start + 2].uncategorized_taxes + statement->quarters[quarter_start + 3].uncategorized_taxes) != 0.0f; bool has_uncategorized_expenses = (statement->quarters[quarter_start + 0].uncategorized_expenses + statement->quarters[quarter_start + 1].uncategorized_expenses + statement->quarters[quarter_start + 2].uncategorized_expenses + statement->quarters[quarter_start + 3].uncategorized_expenses) != 0.0f; // Uncategorized income and expenses if (has_uncategorized_revenue || has_uncategorized_taxes || has_uncategorized_expenses) { ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); ImGui::Text("(%s)", locale::get("statement.uncategorized")); ImGui::TableSetColumnIndex(1); ImGui::Text(""); ImGui::TableSetColumnIndex(2); ImGui::Text(""); ImGui::TableSetColumnIndex(3); ImGui::Text(""); ImGui::TableSetColumnIndex(4); ImGui::Text(""); } if (has_uncategorized_revenue) { ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); ImGui::Text(" %s", locale::get("statement.revenue")); ImGui::TableSetColumnIndex(1); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 0].uncategorized_revenue, currency_symbol); ImGui::TableSetColumnIndex(2); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 1].uncategorized_revenue, currency_symbol); ImGui::TableSetColumnIndex(3); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 2].uncategorized_revenue, currency_symbol); ImGui::TableSetColumnIndex(4); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 3].uncategorized_revenue, currency_symbol); } if (has_uncategorized_taxes) { ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); ImGui::Text(" %s", locale::get("statement.tax")); ImGui::TableSetColumnIndex(1); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 0].uncategorized_taxes, currency_symbol); ImGui::TableSetColumnIndex(2); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 1].uncategorized_taxes, currency_symbol); ImGui::TableSetColumnIndex(3); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 2].uncategorized_taxes, currency_symbol); ImGui::TableSetColumnIndex(4); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 3].uncategorized_taxes, currency_symbol); } if (has_uncategorized_expenses) { ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); ImGui::Text(" %s", locale::get("statement.expenses")); ImGui::TableSetColumnIndex(1); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 0].uncategorized_expenses, currency_symbol); ImGui::TableSetColumnIndex(2); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 1].uncategorized_expenses, currency_symbol); ImGui::TableSetColumnIndex(3); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 2].uncategorized_expenses, currency_symbol); ImGui::TableSetColumnIndex(4); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 3].uncategorized_expenses, currency_symbol); } quarterly_report default_quater = statement->quarters[0]; for (u32 p = 0; p < default_quater.report_count; p++) { project_report* report = &default_quater.reports[p]; ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); bool toggled = ImGui::TreeNodeEx(report->description, ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_DefaultOpen); ImGui::TableSetColumnIndex(1); ImGui::Text(""); ImGui::TableSetColumnIndex(2); ImGui::Text(""); ImGui::TableSetColumnIndex(3); ImGui::Text(""); ImGui::TableSetColumnIndex(4); ImGui::Text(""); if (!toggled) continue; ImGui::PushFont(fontBold); ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); ImGui::Text(" %s", locale::get("statement.revenue")); ImGui::TableSetColumnIndex(1); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 0].reports[p].revenue, currency_symbol); ImGui::TableSetColumnIndex(2); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 1].reports[p].revenue, currency_symbol); ImGui::TableSetColumnIndex(3); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 2].reports[p].revenue, currency_symbol); ImGui::TableSetColumnIndex(4); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 3].reports[p].revenue, currency_symbol); ImGui::PopFont(); ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); ImGui::Text(" %s", locale::get("statement.tax")); ImGui::TableSetColumnIndex(1); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 0].reports[p].taxes, currency_symbol); ImGui::TableSetColumnIndex(2); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 1].reports[p].taxes, currency_symbol); ImGui::TableSetColumnIndex(3); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 2].reports[p].taxes, currency_symbol); ImGui::TableSetColumnIndex(4); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 3].reports[p].taxes, currency_symbol); ImGui::PushFont(fontBold); ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); ImGui::Text(" %s", locale::get("statement.expenses")); ImGui::TableSetColumnIndex(1); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 0].reports[p].expenses_total, currency_symbol); ImGui::TableSetColumnIndex(2); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 1].reports[p].expenses_total, currency_symbol); ImGui::TableSetColumnIndex(3); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 2].reports[p].expenses_total, currency_symbol); ImGui::TableSetColumnIndex(4); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 3].reports[p].expenses_total, currency_symbol); ImGui::PopFont(); for (u32 e = 0; e < report->expense_count; e++) { project_expense* expense = &report->expenses[e]; if (!expense->expense_used_in_project) continue; ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); ImGui::Text(" %s", locale::get(expense->description)); ImGui::TableSetColumnIndex(1); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 0].reports[p].expenses[e].total, currency_symbol); ImGui::TableSetColumnIndex(2); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 1].reports[p].expenses[e].total, currency_symbol); ImGui::TableSetColumnIndex(3); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 2].reports[p].expenses[e].total, currency_symbol); ImGui::TableSetColumnIndex(4); ImGui::Text("%.0f %s", statement->quarters[quarter_start + 3].reports[p].expenses[e].total, currency_symbol); } ImGui::TreePop(); } ImGui::PushFont(fontBold); ImGui::TableNextRow(); ImGui::TableNextColumn(); ImGui::TextUnformatted(locale::get("statement.profit")); #define PUSH_PROFIT_COLUMN(_profit)\ ImGui::TableNextColumn(); \ if (_profit < 0.0f) {\ ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(235, 64, 52, 255));\ ImGui::Text("(%.0f %s)", _profit, currency_symbol);\ ImGui::PopStyleColor();\ }\ else {\ ImGui::Text("%.0f %s", _profit, currency_symbol);\ } PUSH_PROFIT_COLUMN(statement->quarters[quarter_start + 0].profit); PUSH_PROFIT_COLUMN(statement->quarters[quarter_start + 1].profit); PUSH_PROFIT_COLUMN(statement->quarters[quarter_start + 2].profit); PUSH_PROFIT_COLUMN(statement->quarters[quarter_start + 3].profit); ImGui::PopFont(); ImGui::EndTable(); } }