summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/administration.cpp132
-rw-r--r--src/locales.cpp2
-rw-r--r--src/locales/en.cpp16
-rw-r--r--src/ui/ui_contacts.cpp13
-rw-r--r--src/ui/ui_projects.cpp2
-rw-r--r--src/ui/ui_settings.cpp113
6 files changed, 265 insertions, 13 deletions
diff --git a/src/administration.cpp b/src/administration.cpp
index 0353276..e41942e 100644
--- a/src/administration.cpp
+++ b/src/administration.cpp
@@ -2,6 +2,7 @@
#include <stdlib.h>
#include <assert.h>
#include <time.h>
+#include <stdio.h>
#include "strops.hpp"
#include "administration.hpp"
@@ -156,14 +157,41 @@ static void administration_create_default_tax_brackets()
ADD_BRACKET("SE", 12.0f, "tax.reduced");
}
+static void administration_create_default_cost_centers()
+{
+ #define ADD_COSTCENTER(_description, _code)\
+ {\
+ cost_center* tb = (cost_center*)malloc(sizeof(cost_center));\
+ snprintf(tb->id, sizeof(tb->id), "E/%d", administration_create_id());\
+ memcpy(tb->description, _description, sizeof(tb->description));\
+ memcpy(tb->code, _code, sizeof(tb->code));\
+ list_append(&g_administration.cost_centers, tb);\
+ g_administration.next_id++;\
+ }
+
+ ADD_COSTCENTER("costcenter.general_expenses", "GENE");
+ ADD_COSTCENTER("costcenter.administration_general_management", "ADMN");
+ ADD_COSTCENTER("costcenter.finance_accounting", "FINC");
+ ADD_COSTCENTER("costcenter.information_technology", "INFO");
+ ADD_COSTCENTER("costcenter.sales_marketing", "SALE");
+ ADD_COSTCENTER("costcenter.operations_production", "OPER");
+ ADD_COSTCENTER("costcenter.supply_chain_logistics", "SUPP");
+ ADD_COSTCENTER("costcenter.research_development", "RDEV");
+ ADD_COSTCENTER("costcenter.facilities_maintenance", "FACL");
+ ADD_COSTCENTER("costcenter.customer_service_support", "CUST");
+ ADD_COSTCENTER("costcenter.other_specialized", "OTHR");
+}
+
void administration_create()
{
list_init(&g_administration.contacts);
list_init(&g_administration.projects);
list_init(&g_administration.tax_brackets);
+ list_init(&g_administration.cost_centers);
strops_copy(g_administration.path, "", sizeof(g_administration.path));
administration_create_default_tax_brackets();
+ administration_create_default_cost_centers();
}
void administration_destroy()
@@ -171,6 +199,7 @@ void administration_destroy()
list_destroy(&g_administration.contacts);
list_destroy(&g_administration.projects);
list_destroy(&g_administration.tax_brackets);
+ list_destroy(&g_administration.cost_centers);
}
bool administration_create_contact(contact data)
@@ -184,6 +213,13 @@ bool administration_create_contact(contact data)
return true;
}
+bool administration_can_contact_be_deleted(contact data)
+{
+ (void)data;
+ // TODO
+ return true;
+}
+
bool administration_update_contact(contact data)
{
list_iterator_start(&g_administration.contacts);
@@ -285,7 +321,7 @@ u32 administration_get_projects(u32 page_index, u32 page_size, project* buffer)
void administration_cancel_project(project data)
{
data.end_date = time(NULL);
- data.state = project_state::CANCELLED;
+ data.state = project_state::PROJECT_CANCELLED;
administration_update_project(data);
}
@@ -293,9 +329,9 @@ char* administration_project_get_status_string(project data)
{
switch(data.state)
{
- case project_state::RUNNING: return "project.state.running";
- case project_state::PAUSED: return "project.state.paused";
- case project_state::CANCELLED: return "project.state.cancelled";
+ case project_state::PROJECT_RUNNING: return "project.state.running";
+ case project_state::PROJECT_PAUSED: return "project.state.paused";
+ case project_state::PROJECT_CANCELLED: return "project.state.cancelled";
default: assert(0); break;
}
return "";
@@ -303,7 +339,7 @@ char* administration_project_get_status_string(project data)
bool administration_create_project(project data)
{
- data.state = project_state::RUNNING;
+ data.state = project_state::PROJECT_RUNNING;
data.start_date = time(NULL);
data.end_date = 0;
project* new_project = (project*)malloc(sizeof(project));
@@ -378,4 +414,90 @@ u32 administration_get_tax_brackets(country_tax_bracket* buffer)
list_iterator_stop(&g_administration.tax_brackets);
return write_cursor;
+}
+
+u32 administration_get_cost_center_count()
+{
+ return list_size(&g_administration.cost_centers);
+}
+
+u32 administration_get_cost_centers(cost_center* buffer)
+{
+ assert(buffer);
+
+ u32 write_cursor = 0;
+
+ 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);
+ buffer[write_cursor++] = c;
+ }
+ list_iterator_stop(&g_administration.cost_centers);
+
+ return write_cursor;
+}
+
+static bool administration_get_cost_center_by_code(char* code, cost_center* buffer)
+{
+ bool result = false;
+ 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);
+ *buffer = c;
+ if (strcmp(code, c.code) == 0) {
+ result = true;
+ break;
+ }
+ }
+ list_iterator_stop(&g_administration.cost_centers);
+
+ return result;
+}
+
+bool administration_verify_cost_center_description(char* text)
+{
+ return strlen(text) != 0;
+}
+
+bool administration_verify_cost_center_code(char* code)
+{
+ if (strlen(code) == 0) return false;
+
+ cost_center cost_center;
+ bool found = administration_get_cost_center_by_code(code, &cost_center);
+ return !found;
+}
+
+bool administration_add_cost_center(cost_center data)
+{
+ cost_center cs;
+ bool found = administration_get_cost_center_by_code(data.code, &cs);
+ if (found) return false;
+
+ cost_center* tb = (cost_center*)malloc(sizeof(cost_center));
+ snprintf(tb->id, sizeof(tb->id), "E/%d", administration_create_id());
+ memcpy(tb->description, data.description, sizeof(tb->description));
+ memcpy(tb->code, data.code, sizeof(tb->code));
+ list_append(&g_administration.cost_centers, tb);
+
+ g_administration.next_id++;
+
+ return true;
+}
+
+bool administration_update_cost_center(cost_center data)
+{
+ 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, data.id) == 0) {
+ memcpy(c, &data, sizeof(data));
+ list_iterator_stop(&g_administration.cost_centers);
+ return true;
+ }
+ }
+ list_iterator_stop(&g_administration.cost_centers);
+
+ return false;
} \ No newline at end of file
diff --git a/src/locales.cpp b/src/locales.cpp
index 363d3c9..89c8499 100644
--- a/src/locales.cpp
+++ b/src/locales.cpp
@@ -28,5 +28,5 @@ const char* localize(const char* key)
return g_locale.entries[i].value;
}
}
- return "[!MISSING!]";
+ return key;
} \ No newline at end of file
diff --git a/src/locales/en.cpp b/src/locales/en.cpp
index 3c208ef..3c6bafd 100644
--- a/src/locales/en.cpp
+++ b/src/locales/en.cpp
@@ -19,6 +19,19 @@ locale_entry en_locales[] = {
{"form.confirmCancelProject", "Are you sure you want to cancel this Project?"},
{"form.required", "required"},
+ // Default cost centers
+ {"costcenter.general_expenses", "General Expenses"},
+ {"costcenter.administration_general_management", "Administration & General Management"},
+ {"costcenter.finance_accounting", "Finance & Accounting"},
+ {"costcenter.information_technology", "Information Technology (IT)"},
+ {"costcenter.sales_marketing", "Sales & Marketing"},
+ {"costcenter.operations_production", "Operations / Production"},
+ {"costcenter.supply_chain_logistics", "Supply Chain & Logistics"},
+ {"costcenter.research_development", "Research & Development"},
+ {"costcenter.facilities_maintenance", "Facilities & Maintenance"},
+ {"costcenter.customer_service_support", "Customer Service & Support"},
+ {"costcenter.other_specialized", "Other / Specialized"},
+
// Tax strings.
{"tax.reverse_charge", "Reverse tax"},
{"tax.exempt", "Tax exempt"},
@@ -93,8 +106,11 @@ locale_entry en_locales[] = {
// Settings strings.
{"settings.table.company", "Company"},
{"settings.table.vatrates", "VAT Rates"},
+ {"settings.table.costcenters", "Cost Centers"},
{"settings.vat.table.country", "Country"},
{"settings.vat.table.rates", "Rates"},
+ {"settings.costcenters.table.code", "Code"},
+ {"settings.costcenters.table.description", "Description"},
};
const int en_locale_count = sizeof(en_locales) / sizeof(en_locales[0]); \ No newline at end of file
diff --git a/src/ui/ui_contacts.cpp b/src/ui/ui_contacts.cpp
index 24f45f7..e00fb78 100644
--- a/src/ui/ui_contacts.cpp
+++ b/src/ui/ui_contacts.cpp
@@ -196,12 +196,13 @@ static void draw_contact_list()
}
ImGui::SameLine();
-
- // TODO check to make sure no invoices are connected to this contact.
- snprintf(btn_name, sizeof(btn_name), "%s##%d", localize("form.delete"), i);
- if (ImGui::Button(btn_name)) {
- selected_for_removal = c;
- ImGui::OpenPopup("ConfirmDeletePopup");
+ if (administration_can_contact_be_deleted(c))
+ {
+ snprintf(btn_name, sizeof(btn_name), "%s##%d", localize("form.delete"), i);
+ if (ImGui::Button(btn_name)) {
+ selected_for_removal = c;
+ ImGui::OpenPopup("ConfirmDeletePopup");
+ }
}
}
diff --git a/src/ui/ui_projects.cpp b/src/ui/ui_projects.cpp
index a831f60..377155e 100644
--- a/src/ui/ui_projects.cpp
+++ b/src/ui/ui_projects.cpp
@@ -130,7 +130,7 @@ static void draw_project_list()
current_view_state = view_state::VIEW;
}
- if (c.state == project_state::RUNNING)
+ if (c.state == project_state::PROJECT_RUNNING)
{
ImGui::SameLine();
snprintf(btn_name, sizeof(btn_name), "%s##%d", localize("form.change"), i);
diff --git a/src/ui/ui_settings.cpp b/src/ui/ui_settings.cpp
index 97e0503..7854be3 100644
--- a/src/ui/ui_settings.cpp
+++ b/src/ui/ui_settings.cpp
@@ -10,9 +10,19 @@
extern bool draw_contact_form(contact* buffer, bool back_button_enabled = true, bool viewing_only = false);
static contact company_info;
+
country_tax_bracket* tax_brackets;
u32 tax_bracket_count;
+cost_center* cost_centers;
+u32 cost_center_count;
+
+void ui_destroy_settings()
+{
+ free(tax_brackets);
+ free(cost_centers);
+}
+
void ui_setup_settings()
{
company_info = administration_get_company_info();
@@ -20,6 +30,10 @@ void ui_setup_settings()
tax_bracket_count = administration_get_tax_bracket_count();
tax_brackets = (country_tax_bracket*)malloc(tax_bracket_count * sizeof(country_tax_bracket));
administration_get_tax_brackets(tax_brackets);
+
+ cost_center_count = administration_get_cost_center_count();
+ cost_centers = (cost_center*)malloc(cost_center_count * sizeof(cost_center));
+ administration_get_cost_centers(cost_centers);
}
static void ui_draw_vat_rates()
@@ -66,6 +80,100 @@ static void ui_draw_vat_rates()
}
}
+static void ui_draw_cost_centers()
+{
+ static bool is_adding_item = false;
+ static cost_center new_cost_center;
+
+ static bool is_editing_item = false;
+ static u32 editing_item_index = 0;
+
+ if (ImGui::BeginTable("TableCostCenters", 2, ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg)) {
+
+ ImGui::TableSetupColumn(localize("settings.costcenters.table.code"), ImGuiTableColumnFlags_WidthFixed, 140);
+ ImGui::TableSetupColumn(localize("settings.costcenters.table.description"));
+
+ for (u32 i = 0; i < cost_center_count; i++) {
+ cost_center c = cost_centers[i];
+
+ ImGui::TableNextRow();
+ ImGui::TableSetColumnIndex(0); ImGui::Text(c.code);
+ ImGui::TableSetColumnIndex(1);
+
+ if (is_editing_item && editing_item_index == i)
+ {
+ ImGui::InputText("##Description", new_cost_center.description, IM_ARRAYSIZE(new_cost_center.description));
+
+ bool is_desc_valid = administration_verify_cost_center_description(new_cost_center.description);
+
+ if (!is_desc_valid) ImGui::BeginDisabled();
+ ImGui::SameLine();
+ if (ImGui::Button(localize("form.save"))) {
+ is_editing_item = false;
+ is_adding_item = false;
+
+ administration_update_cost_center(new_cost_center);
+
+ ui_destroy_settings();
+ ui_setup_settings();
+ }
+ if (!is_desc_valid) ImGui::EndDisabled();
+ }
+ else
+ {
+ ImGui::Text(localize(c.description));
+ }
+
+ if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left))
+ {
+ is_editing_item = true;
+ is_adding_item = false;
+ editing_item_index = i;
+ new_cost_center = c;
+ }
+ }
+
+ if (is_adding_item)
+ {
+ ImGui::TableNextRow();
+
+ bool is_code_valid = administration_verify_cost_center_code(new_cost_center.code);
+ if (!is_code_valid) ImGui::PushStyleColor(ImGuiCol_FrameBg, IM_COL32(255, 0, 0, 64));
+ ImGui::TableSetColumnIndex(0); ImGui::InputText("##Code", new_cost_center.code, IM_ARRAYSIZE(new_cost_center.code));
+ if (!is_code_valid) ImGui::PopStyleColor();
+
+ bool is_desc_valid = administration_verify_cost_center_description(new_cost_center.description);
+ if (!is_desc_valid) ImGui::PushStyleColor(ImGuiCol_FrameBg, IM_COL32(255, 0, 0, 64));
+ ImGui::TableSetColumnIndex(1); ImGui::InputText("##Description", new_cost_center.description, IM_ARRAYSIZE(new_cost_center.description));
+ if (!is_desc_valid) ImGui::PopStyleColor();
+
+ bool can_save = is_code_valid && is_desc_valid;
+
+ if (!can_save) ImGui::BeginDisabled();
+ ImGui::SameLine();
+ if (ImGui::Button(localize("form.create")))
+ {
+ is_adding_item = false;
+ is_editing_item = false;
+ administration_add_cost_center(new_cost_center);
+
+ ui_destroy_settings();
+ ui_setup_settings();
+ }
+ if (!can_save) ImGui::EndDisabled();
+ }
+
+ ImGui::EndTable();
+ }
+
+ if (!is_adding_item && ImGui::Button(localize("form.create")))
+ {
+ is_adding_item = true;
+ is_editing_item = false;
+ memset(&new_cost_center, 0, sizeof(new_cost_center));
+ }
+}
+
void ui_draw_settings()
{
if (ImGui::BeginTabBar("SettingsTabBar"))
@@ -84,6 +192,11 @@ void ui_draw_settings()
ui_draw_vat_rates();
ImGui::EndTabItem();
}
+ if (ImGui::BeginTabItem(localize("settings.table.costcenters")))
+ {
+ ui_draw_cost_centers();
+ ImGui::EndTabItem();
+ }
ImGui::EndTabBar();
}
} \ No newline at end of file