summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAldrik Ramaekers <aldrikboy@gmail.com>2025-08-17 16:10:48 +0200
committerAldrik Ramaekers <aldrikboy@gmail.com>2025-08-17 16:10:48 +0200
commitb676299f983b6fc00458953d90efe3f784b86d62 (patch)
tree1129be0f65eb4d0ce734c8f7074d985a70869202
parentc4ae6cfd53a0fc3ec94ab2aae9e2984a2b48da8f (diff)
expense views
-rw-r--r--include/administration.hpp6
-rw-r--r--src/administration.cpp48
-rw-r--r--src/locales/en.cpp1
-rw-r--r--src/ui/ui_expenses.cpp49
-rw-r--r--src/ui/ui_invoices.cpp14
5 files changed, 83 insertions, 35 deletions
diff --git a/include/administration.hpp b/include/administration.hpp
index 9c07f30..e2e61ca 100644
--- a/include/administration.hpp
+++ b/include/administration.hpp
@@ -89,6 +89,7 @@ typedef enum
INVOICE_CANCELLED,
INVOICE_REFUNDED,
INVOICE_CORRECTED,
+ INVOICE_RECEIVED,
} invoice_status;
typedef struct
@@ -134,6 +135,7 @@ typedef struct
char currency[MAX_LEN_CURRENCY]; // 3 letter code
bool is_triangulation; // True of addressee != customer
invoice_status status;
+ bool is_outgoing; // Outgoing or incomming invoice.
bool is_intra_community; // TODO uninplemented
time_t payment_on_account_date; // TODO uninplemented
@@ -156,7 +158,6 @@ typedef struct
list_t contacts;
list_t projects;
list_t invoices;
- list_t expenses;
list_t tax_brackets;
list_t cost_centers;
} administration;
@@ -236,7 +237,8 @@ invoice administration_invoice_create_copy(invoice* invoice);
bool administration_invoice_is_valid(invoice* invoice);
char* administration_invoice_get_status_string(invoice* invoice);
-u32 administration_invoice_get_partial_list(u32 page_index, u32 page_size, invoice* buffer);
+u32 administration_invoice_get_partial_list_outgoing(u32 page_index, u32 page_size, invoice* buffer);
+u32 administration_invoice_get_partial_list_incomming(u32 page_index, u32 page_size, invoice* buffer);
// Billing item functions.
// =======================
diff --git a/src/administration.cpp b/src/administration.cpp
index 66e4a46..45a1125 100644
--- a/src/administration.cpp
+++ b/src/administration.cpp
@@ -293,7 +293,6 @@ void administration_create()
g_administration.next_sequence_number = 1;
list_init(&g_administration.invoices);
- list_init(&g_administration.expenses);
list_init(&g_administration.contacts);
list_init(&g_administration.projects);
list_init(&g_administration.tax_brackets);
@@ -319,7 +318,6 @@ static void administration_destroy_list(list_t *list)
void administration_destroy()
{
administration_destroy_list(&g_administration.invoices);
- administration_destroy_list(&g_administration.expenses);
administration_destroy_list(&g_administration.contacts);
administration_destroy_list(&g_administration.projects);
administration_destroy_list(&g_administration.tax_brackets);
@@ -927,6 +925,19 @@ bool administration_invoice_update(invoice* inv)
inv->customer = new_contact;
}
+ // Supplier is valid but supplier id is unset means we need to register a new contact.
+ if (strcmp(inv->supplier_id, "") == 0)
+ {
+ contact new_contact = administration_contact_create_empty();
+ strops_copy(inv->supplier_id, new_contact.id, sizeof(new_contact.id));
+ strops_copy(inv->supplier.id, new_contact.id, sizeof(new_contact.id));
+
+ memcpy(&new_contact, &inv->supplier, sizeof(contact));
+ administration_contact_add(new_contact);
+
+ inv->supplier = new_contact;
+ }
+
// Addressee is same as customer.
if (!inv->is_triangulation)
{
@@ -986,6 +997,19 @@ bool administration_invoice_add(invoice* inv)
inv->customer = new_contact;
}
+ // Supplier is valid but supplier id is unset means we need to register a new contact.
+ if (strcmp(inv->supplier_id, "") == 0)
+ {
+ contact new_contact = administration_contact_create_empty();
+ strops_copy(inv->supplier_id, new_contact.id, sizeof(new_contact.id));
+ strops_copy(inv->supplier.id, new_contact.id, sizeof(new_contact.id));
+
+ memcpy(&new_contact, &inv->supplier, sizeof(contact));
+ administration_contact_add(new_contact);
+
+ inv->supplier = new_contact;
+ }
+
// Addressee is same as customer.
if (!inv->is_triangulation)
{
@@ -995,8 +1019,6 @@ bool administration_invoice_add(invoice* inv)
invoice copy = administration_invoice_create_copy(inv); // Create copy to make copy of billing item list.
invoice* new_inv = (invoice*)malloc(sizeof(invoice));
memcpy(new_inv, &copy, sizeof(invoice));
-
- new_inv->status = invoice_status::INVOICE_CONCEPT;
list_append(&g_administration.invoices, new_inv);
@@ -1011,17 +1033,20 @@ u32 administration_invoice_count()
return list_size(&g_administration.invoices);
}
-u32 administration_invoice_get_partial_list(u32 page_index, u32 page_size, invoice* buffer)
+static u32 administration_invoice_get_partial_list(u32 page_index, u32 page_size, invoice* buffer, bool want_outgoing)
{
assert(buffer);
u32 write_cursor = 0;
u32 read_start = page_index * page_size;
+ u32 read_cursor = 0;
list_iterator_start(&g_administration.invoices);
while (list_iterator_hasnext(&g_administration.invoices)) {
invoice c = *(invoice *)list_iterator_next(&g_administration.invoices);
- if (g_administration.invoices.iter_pos <= read_start) continue;
+ if (c.is_outgoing != want_outgoing) continue; // Continue without incrementing read cursor
+ read_cursor++;
+ if (read_cursor <= read_start) continue;
buffer[write_cursor++] = c;
if (write_cursor >= page_size) break;
@@ -1031,6 +1056,16 @@ u32 administration_invoice_get_partial_list(u32 page_index, u32 page_size, invoi
return write_cursor;
}
+u32 administration_invoice_get_partial_list_outgoing(u32 page_index, u32 page_size, invoice* buffer)
+{
+ return administration_invoice_get_partial_list(page_index, page_size, buffer, 1);
+}
+
+u32 administration_invoice_get_partial_list_incomming(u32 page_index, u32 page_size, invoice* buffer)
+{
+ return administration_invoice_get_partial_list(page_index, page_size, buffer, 0);
+}
+
char* administration_invoice_get_status_string(invoice* invoice)
{
switch(invoice->status)
@@ -1043,6 +1078,7 @@ char* administration_invoice_get_status_string(invoice* invoice)
case invoice_status::INVOICE_CANCELLED: return "invoice.status.cancelled";
case invoice_status::INVOICE_REFUNDED: return "invoice.status.refunded";
case invoice_status::INVOICE_CORRECTED: return "invoice.status.corrected";
+ case invoice_status::INVOICE_RECEIVED: return "invoice.status.received";
default: assert(0); break;
}
return "";
diff --git a/src/locales/en.cpp b/src/locales/en.cpp
index b7312f6..c2b0738 100644
--- a/src/locales/en.cpp
+++ b/src/locales/en.cpp
@@ -151,6 +151,7 @@ locale_entry en_locales[] = {
{"invoice.status.cancelled", "Cancelled"},
{"invoice.status.refunded", "Refunded"},
{"invoice.status.corrected", "Corrected"},
+ {"invoice.status.received", "Received"},
};
const int en_locale_count = sizeof(en_locales) / sizeof(en_locales[0]); \ No newline at end of file
diff --git a/src/ui/ui_expenses.cpp b/src/ui/ui_expenses.cpp
index 3df0994..94b0b36 100644
--- a/src/ui/ui_expenses.cpp
+++ b/src/ui/ui_expenses.cpp
@@ -246,6 +246,8 @@ static void draw_expense_items_form(invoice* invoice)
static void draw_expense_form(invoice* buffer, bool viewing_only = false)
{
+ if (viewing_only) ImGui::BeginDisabled();
+
// 1. Identifier
//ImGui::SetNextItemWidth(widthAvailable*0.2f);
//ImGui::InputText(localize("contact.form.identifier"), buffer->id, IM_ARRAYSIZE(buffer->id));
@@ -302,6 +304,7 @@ static void draw_expense_form(invoice* buffer, bool viewing_only = false)
if (!administration_contact_equals(lookup_buffer, buffer->supplier))
{
buffer->supplier_id[0] = '\0';
+ buffer->supplier.id[0] = '\0';
}
}
@@ -346,13 +349,19 @@ static void draw_expense_form(invoice* buffer, bool viewing_only = false)
// 13. Invoice items form
draw_expense_items_form(buffer);
+
+ if (viewing_only) ImGui::EndDisabled();
}
static void ui_draw_expenses_list()
{
const u32 items_per_page = 50;
static s32 current_page = 0;
- s32 max_page = (administration_invoice_count() + items_per_page - 1) / items_per_page;
+
+ invoice invoice_list[items_per_page];
+ u32 invoice_count = administration_invoice_get_partial_list_incomming(current_page, items_per_page, invoice_list);
+
+ s32 max_page = (invoice_count + items_per_page - 1) / items_per_page;
if (max_page == 0) max_page = 1;
// Table header controls: create button and pagination.
@@ -361,6 +370,8 @@ static void ui_draw_expenses_list()
current_view_state = view_state::CREATE;
active_invoice = administration_invoice_create_empty(); // @leak
active_invoice.customer = administration_company_info_get();
+ active_invoice.is_outgoing = 0;
+ active_invoice.status = invoice_status::INVOICE_RECEIVED;
strops_copy(active_invoice.customer_id, active_invoice.customer.id, sizeof(active_invoice.customer_id));
}
@@ -397,9 +408,6 @@ static void ui_draw_expenses_list()
ImGui::TableSetupColumn("");
ImGui::TableHeadersRow();
- invoice invoice_list[items_per_page];
- u32 invoice_count = administration_invoice_get_partial_list(current_page, items_per_page, invoice_list);
-
for (u32 i = 0; i < invoice_count; i++) {
invoice c = invoice_list[i];
@@ -426,20 +434,17 @@ static void ui_draw_expenses_list()
ImGui::SameLine();
- if (c.status == invoice_status::INVOICE_CONCEPT)
- {
- snprintf(btn_name, sizeof(btn_name), "%s##%d", localize("form.change"), i);
- if (ImGui::Button(btn_name)) {
- active_invoice = administration_invoice_create_copy(&c); // We create a copy because of billing item list pointers.
- current_view_state = view_state::EDIT;
- }
-
- ImGui::SameLine();
- snprintf(btn_name, sizeof(btn_name), "%s##%d", localize("form.delete"), i);
- if (ImGui::Button(btn_name)) {
- selected_for_removal = c;
- ImGui::OpenPopup("ConfirmDeletePopup");
- }
+ snprintf(btn_name, sizeof(btn_name), "%s##%d", localize("form.change"), i);
+ if (ImGui::Button(btn_name)) {
+ active_invoice = administration_invoice_create_copy(&c); // We create a copy because of billing item list pointers.
+ current_view_state = view_state::EDIT;
+ }
+
+ ImGui::SameLine();
+ snprintf(btn_name, sizeof(btn_name), "%s##%d", localize("form.delete"), i);
+ if (ImGui::Button(btn_name)) {
+ selected_for_removal = c;
+ ImGui::OpenPopup("ConfirmDeletePopup");
}
}
@@ -480,8 +485,8 @@ static void ui_draw_expense_update()
administration_invoice_update(&active_invoice);
current_view_state = view_state::LIST;
- ui_destroy_invoices();
- ui_setup_invoices();
+ ui_destroy_expenses();
+ ui_setup_expenses();
}
if (!can_save) ImGui::EndDisabled();
@@ -503,8 +508,8 @@ static void ui_draw_expense_create()
administration_invoice_add(&active_invoice);
current_view_state = view_state::LIST;
- ui_destroy_invoices();
- ui_setup_invoices();
+ ui_destroy_expenses();
+ ui_setup_expenses();
}
if (!can_save) ImGui::EndDisabled();
diff --git a/src/ui/ui_invoices.cpp b/src/ui/ui_invoices.cpp
index 04b0da4..2ae0aae 100644
--- a/src/ui/ui_invoices.cpp
+++ b/src/ui/ui_invoices.cpp
@@ -324,6 +324,7 @@ static void draw_invoice_form(invoice* buffer, bool viewing_only = false)
if (!administration_contact_equals(lookup_buffer, buffer->customer))
{
buffer->customer_id[0] = '\0';
+ buffer->customer.id[0] = '\0';
}
}
@@ -369,7 +370,11 @@ static void ui_draw_invoices_list()
{
const u32 items_per_page = 50;
static s32 current_page = 0;
- s32 max_page = (administration_invoice_count() + items_per_page - 1) / items_per_page;
+
+ invoice invoice_list[items_per_page];
+ u32 invoice_count = administration_invoice_get_partial_list_outgoing(current_page, items_per_page, invoice_list);
+
+ s32 max_page = (invoice_count + items_per_page - 1) / items_per_page;
if (max_page == 0) max_page = 1;
// Table header controls: create button and pagination.
@@ -378,6 +383,8 @@ static void ui_draw_invoices_list()
current_view_state = view_state::CREATE;
active_invoice = administration_invoice_create_empty(); // @leak
active_invoice.supplier = administration_company_info_get();
+ active_invoice.is_outgoing = 1;
+ active_invoice.status = invoice_status::INVOICE_CONCEPT;
strops_copy(active_invoice.supplier_id, active_invoice.supplier.id, sizeof(active_invoice.supplier_id));
}
@@ -412,10 +419,7 @@ static void ui_draw_invoices_list()
ImGui::TableSetupColumn(localize("invoice.table.total"));
ImGui::TableSetupColumn(localize("invoice.table.status"));
ImGui::TableSetupColumn("");
- ImGui::TableHeadersRow();
-
- invoice invoice_list[items_per_page];
- u32 invoice_count = administration_invoice_get_partial_list(current_page, items_per_page, invoice_list);
+ ImGui::TableHeadersRow();
for (u32 i = 0; i < invoice_count; i++) {
invoice c = invoice_list[i];