summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAldrik Ramaekers <aldrik@mailbox.org>2026-01-03 11:03:50 +0100
committerAldrik Ramaekers <aldrik@mailbox.org>2026-01-03 11:03:50 +0100
commit83a9739b3aff75cf767db687bd531fa5283e0e72 (patch)
treeadf130cb7728a4358062a040f6322ecc236d0e6b /src
parent2218ef68056ebc5a3a416e2dd7e8e020fba60a4f (diff)
move invoice status to invoice extras struct. implement r/w
Diffstat (limited to 'src')
-rw-r--r--src/administration.cpp3
-rw-r--r--src/administration_reader.cpp40
-rw-r--r--src/administration_writer.cpp38
-rw-r--r--src/importer.cpp2
-rw-r--r--src/ui/ui_expenses.cpp4
-rw-r--r--src/ui/ui_invoices.cpp7
6 files changed, 80 insertions, 14 deletions
diff --git a/src/administration.cpp b/src/administration.cpp
index 77e8754..6e7d2f1 100644
--- a/src/administration.cpp
+++ b/src/administration.cpp
@@ -1397,6 +1397,7 @@ invoice administration::invoice_create_empty()
strops::format(result.sequential_number, sizeof(result.id), "INV%010d", create_sequence_number());
result.issued_at = time(NULL);
result.issued_at -= (result.issued_at % 86400);
+ result.extras.status = invoice_status::INVOICE_CONCEPT;
result.delivered_at = result.issued_at;
result.expires_at = result.issued_at + administration::get_default_invoice_expire_duration();
@@ -1752,7 +1753,7 @@ u32 administration::invoice_get_partial_list_incomming(u32 page_index, u32 page_
char* administration::invoice_get_status_string(invoice* invoice)
{
- switch(invoice->status)
+ switch(invoice->extras.status)
{
case invoice_status::INVOICE_CONCEPT: return "invoice.status.concept";
case invoice_status::INVOICE_SENT: return "invoice.status.sent";
diff --git a/src/administration_reader.cpp b/src/administration_reader.cpp
index d790b91..3706e72 100644
--- a/src/administration_reader.cpp
+++ b/src/administration_reader.cpp
@@ -92,7 +92,7 @@ bool administration_reader::open_existing(char* file_path)
}
else if (strops::is_prefixed("I/", name))
{
- administration_reader::import_invoice(buffer, (size_t)size);
+ administration_reader::import_invoice(zip, buffer, (size_t)size);
}
memops::unalloc(buffer);
}
@@ -123,7 +123,7 @@ bool administration_reader::read_invoice_from_xml(invoice* result, char* buffer,
xml_get_str(root, data.id, MAX_LEN_ID, "cbc:ID");
xml_get_str_x(root, data.sequential_number, MAX_LEN_ID, "cac:OrderReference", "cbc:ID", 0);
xml_get_str(root, data.currency, MAX_LEN_CURRENCY, "cbc:DocumentCurrencyCode");
- data.status = (invoice_status)xml_get_s32_x(root, "cac:DespatchDocumentReference", "cbc:ID", 0);
+ //data.status = (invoice_status)xml_get_s32_x(root, "cac:DespatchDocumentReference", "cbc:ID", 0);
// Dates
data.issued_at = xml_get_date_x(root, "cbc:IssueDate", 0);
@@ -232,12 +232,46 @@ bool administration_reader::read_invoice_from_xml(invoice* result, char* buffer,
return true;
}
-bool administration_reader::import_invoice(char* buffer, size_t buffer_size)
+static bool _import_invoice_extras(zip_t* zip, invoice* data)
+{
+ STOPWATCH_START;
+
+ char final_path[50];
+ strops::format(final_path, 50, "EXTRAS/%s.xml", data->sequential_number);
+ if (zip_entry_open(zip, final_path) < 0) {
+ logger::error("ERROR loading invoice extras for '%s', file '%s' does not exist.", data->sequential_number, final_path);
+ return false;
+ }
+
+ // Load into buffer.
+ char* buffer;
+ unsigned long long size;
+ zip_entry_read(zip, (void**)&buffer, (size_t*)&size);
+
+ xml_document* document = xml_parse_document((uint8_t *)buffer, size);
+ if (!document) return false;
+
+ struct xml_node* root = xml_document_root(document);
+ if (!root) {
+ xml_document_free(document, false);
+ return false;
+ }
+
+ data->extras.status = (invoice_status)xml_get_s32_x(root, "Status", 0);
+
+ logger::info("Loaded invoice extras '%s' in %.3fms.", final_path, STOPWATCH_TIME);
+
+ return true;
+}
+
+bool administration_reader::import_invoice(zip_t* zip, char* buffer, size_t buffer_size)
{
STOPWATCH_START;
invoice data;
if (!administration_reader::read_invoice_from_xml(&data, buffer, buffer_size)) return false;
+ if (!_import_invoice_extras(zip, &data)) return false;
+ printf("%d\n", data.extras.status);
a_err result = administration::invoice_import(&data);
if (result == A_ERR_SUCCESS) {
diff --git a/src/administration_writer.cpp b/src/administration_writer.cpp
index 8304e5c..3191be7 100644
--- a/src/administration_writer.cpp
+++ b/src/administration_writer.cpp
@@ -240,7 +240,7 @@ void administration_writer::destroy()
static char* copy_template(const char* template_str, int* buf_size)
{
size_t template_size = strops::length(template_str);
- size_t buf_length = template_size*5; // Ballpark file content size.
+ size_t buf_length = template_size*5; // Ballpark file content size. // @TODO
char* file_content = (char*)memops::alloc(buf_length);
memops::zero(file_content, buf_length);
memops::copy(file_content, template_str, template_size);
@@ -504,12 +504,40 @@ static void _add_document_to_zip(invoice* inv)
}
}
+bool _save_invoice_extras(invoice inv)
+{
+ STOPWATCH_START;
+
+ bool result = 1;
+ int buf_length = 0;
+ char* file_content = copy_template(file_template::invoice_extras_template, &buf_length);
+
+ strops::replace_int32(file_content, buf_length, "{{INVOICE_STATUS}}", (s32)inv.extras.status);
+
+ //// Write to Disk.
+ char final_path[50];
+ strops::format(final_path, 50, "EXTRAS/%s.xml", inv.sequential_number);
+
+ int final_length = (int)strops::length(file_content);
+ if (!xml_string_is_valid((uint8_t*)file_content, final_length)) result = 0;
+ else if (!write_to_zip(final_path, file_content, final_length)) result = 0;
+
+ memops::unalloc(file_content);
+
+ if (result) logger::info("Saved invoice extras for '%s' in %.3fms.", inv.sequential_number, STOPWATCH_TIME);
+ else logger::error("Failed to save invoice extras for '%s'.", inv.sequential_number);
+
+ return result;
+}
+
bool administration_writer::save_invoice_blocking(invoice inv)
{
+ _save_invoice_extras(inv);
+
STOPWATCH_START;
bool result = 1;
- int buf_length = 150000; // Ballpark file content size.
+ int buf_length = 150000; // Ballpark file content size. // @TODO
char* file_content = (char*)memops::alloc(buf_length);
memops::zero(file_content, buf_length);
memops::copy(file_content, file_template::peppol_invoice_template, strops::length(file_template::peppol_invoice_template));
@@ -526,7 +554,7 @@ bool administration_writer::save_invoice_blocking(invoice inv)
strops::replace(file_content, buf_length, "{{COST_CENTER_ID}}", inv.cost_center_id);
strops::replace(file_content, buf_length, "{{INVOICE_DOCUMENT_COPY}}", inv.document.copy_path);
strops::replace(file_content, buf_length, "{{INVOICE_DOCUMENT_ORIG}}", inv.document.original_path);
- strops::replace_int32(file_content, buf_length, "{{INVOICE_STATUS}}", (s32)inv.status);
+ //strops::replace_int32(file_content, buf_length, "{{INVOICE_STATUS}}", (s32)inv.status);
// Supplier data
strops::replace(file_content, buf_length, "{{SUPPLIER_ENDPOINT_SCHEME}}", get_eas_scheme_for_contact(inv.supplier));
@@ -587,7 +615,7 @@ bool administration_writer::save_invoice_blocking(invoice inv)
tax_rate* tax_rate_buffer = (tax_rate*)memops::alloc(sizeof(tax_rate)*administration::billing_item_count(&inv));
u32 tax_rate_count = administration::invoice_get_tax_rates(&inv, tax_rate_buffer);
- u32 tax_subtotal_list_buffer_size = (u32)strops::length(file_template::peppol_invoice_tax_subtotal_template) * 2 * tax_rate_count; // Ballpark list size.
+ u32 tax_subtotal_list_buffer_size = (u32)strops::length(file_template::peppol_invoice_tax_subtotal_template) * 2 * tax_rate_count; // Ballpark list size. // @TODO
char* tax_subtotal_list_buffer = (char*)memops::alloc(tax_subtotal_list_buffer_size);
memops::zero(tax_subtotal_list_buffer, tax_subtotal_list_buffer_size);
u32 tax_subtotal_list_buffer_cursor = 0;
@@ -631,7 +659,7 @@ bool administration_writer::save_invoice_blocking(invoice inv)
billing_item* billing_item_buffer = (billing_item*)memops::alloc(sizeof(billing_item) * administration::billing_item_count(&inv));
u32 billing_item_count = administration::billing_item_get_all_for_invoice(&inv, billing_item_buffer);
- u32 billing_item_list_buffer_size = (u32)strops::length(file_template::peppol_invoice_line_template) * 2 * billing_item_count; // Ballpark list size.
+ u32 billing_item_list_buffer_size = (u32)strops::length(file_template::peppol_invoice_line_template) * 2 * billing_item_count; // Ballpark list size. // @TODO
char* billing_item_list_buffer = (char*)memops::alloc(billing_item_list_buffer_size);
memops::zero(billing_item_list_buffer, billing_item_list_buffer_size);
u32 billing_item_list_buffer_cursor = 0;
diff --git a/src/importer.cpp b/src/importer.cpp
index 3c56062..65726bc 100644
--- a/src/importer.cpp
+++ b/src/importer.cpp
@@ -255,7 +255,7 @@ static int _ai_document_to_invoice_t(void *arg)
return 0;
}
- inv.status = invoice_status::INVOICE_RECEIVED;
+ inv.extras.status = invoice_status::INVOICE_RECEIVED;
inv.is_triangulation = !memops::equals(&inv.addressee.address, &inv.customer.address, sizeof(address));
diff --git a/src/ui/ui_expenses.cpp b/src/ui/ui_expenses.cpp
index 4227e08..7f8d1cc 100644
--- a/src/ui/ui_expenses.cpp
+++ b/src/ui/ui_expenses.cpp
@@ -179,7 +179,7 @@ static void draw_expenses_list()
active_invoice = administration::invoice_create_empty();
active_invoice.customer = administration::company_info_get();
active_invoice.is_outgoing = 0;
- active_invoice.status = invoice_status::INVOICE_RECEIVED;
+ active_invoice.extras.status = invoice_status::INVOICE_RECEIVED;
}
char import_file_path[MAX_LEN_PATH] = {0};
@@ -189,7 +189,7 @@ static void draw_expenses_list()
active_invoice = administration::invoice_create_empty();
active_invoice.customer = administration::company_info_get();
active_invoice.is_outgoing = 0;
- active_invoice.status = invoice_status::INVOICE_RECEIVED;
+ active_invoice.extras.status = invoice_status::INVOICE_RECEIVED;
active_import_request = importer::ai_document_to_invoice(import_file_path);
}
diff --git a/src/ui/ui_invoices.cpp b/src/ui/ui_invoices.cpp
index a5fbd3c..519544b 100644
--- a/src/ui/ui_invoices.cpp
+++ b/src/ui/ui_invoices.cpp
@@ -287,7 +287,6 @@ static void draw_invoices_list()
_set_active_invoice(administration::invoice_create_empty());
active_invoice.supplier = administration::company_info_get();
active_invoice.is_outgoing = 1;
- active_invoice.status = invoice_status::INVOICE_CONCEPT;
}
if (current_page >= max_page-1) current_page = max_page-1;
@@ -478,7 +477,11 @@ static void draw_send_options()
active_request = exporter::send_email("test@test-vz9dlemj2564kj50.mlsender.net", "aldrikboy@gmail.com", "test", "test 123",
[](e_err status) {
if (status == E_ERR_SUCCESS) {
- administration::activity_add(ACTIVITY_USER, active_invoice.id, "Sent email", 0);
+ active_invoice.extras.status = invoice_status::INVOICE_SENT;
+ administration::invoice_update(&active_invoice);
+ administration::activity_add(ACTIVITY_USER, active_invoice.id, "Invoice status changed", 0); // @locale
+ administration::activity_add(ACTIVITY_USER, active_invoice.id, "Sent email", 0); // @locale
+
_reload_activities();
}
});