summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--TODO2
-rw-r--r--include/administration.hpp7
-rw-r--r--include/administration_writer.hpp11
-rw-r--r--include/file_templates.hpp8
-rw-r--r--src/administration.cpp37
-rw-r--r--src/administration_reader.cpp2
-rw-r--r--src/administration_writer.cpp53
-rw-r--r--src/main_linux.cpp8
-rw-r--r--src/ui/ui_invoices.cpp4
9 files changed, 91 insertions, 41 deletions
diff --git a/TODO b/TODO
index 13b66da..d2f301d 100644
--- a/TODO
+++ b/TODO
@@ -12,9 +12,9 @@ Testing:
- write tests that check error handling for corrupt files. (e.g. references to tax rates, project and cost center that failed to load)
Features:
+- save api keys for all options individually so user can switch without losing key
- Refactor contact and project UI to be like invoice & expenses
- Timeline for invoice modifications (e.g. edited, status changed, paid)
-- When creating a new openbooks file, user should only be able to set company info before anything else.
- Show AI balance available in settings page
- Handle invalid api key response from AI backends and display in settings UI
- error log for tax report to display invoices not yet supported for tax generation or invoices with invalid tax rates
diff --git a/include/administration.hpp b/include/administration.hpp
index d899987..1fac81c 100644
--- a/include/administration.hpp
+++ b/include/administration.hpp
@@ -424,9 +424,7 @@ typedef struct
time_t timestamp;
char user_name[MAX_LEN_SHORT_DESC];
char ref_id[MAX_LEN_ID];
-
char message[MAX_LEN_LONG_DESC];
- char params[ACTIVITY_MAX_PARAMS][MAX_LEN_LONG_DESC];
} activity;
typedef struct
@@ -627,7 +625,8 @@ namespace administration {
// Activity functions.
// ===================
- a_err activity_add(char* user, char* ref_id, char* message, ...);
+ a_err activity_add(char* user, char* ref_id, char* message);
u32 activity_get_all_for_object(activity* buffer, char* ref_id);
-
+ u32 activity_count();
+ a_err activity_get_by_index(u32 index, activity* buffer);
} \ No newline at end of file
diff --git a/include/administration_writer.hpp b/include/administration_writer.hpp
index 488330b..81630a7 100644
--- a/include/administration_writer.hpp
+++ b/include/administration_writer.hpp
@@ -18,7 +18,8 @@
#include "administration.hpp"
-#define ADMIN_FILE_INFO "info.xml"
+#define ACTIVITY_FILE "activities.xml"
+#define ADMIN_INFO_FILE "info.xml"
typedef void (*write_completed_event)();
@@ -33,20 +34,14 @@ namespace administration_writer {
bool create();
void destroy();
- bool start_new();
-
- // Individual entity writing.
bool delete_entry(const char* id);
bool save_project_blocking(project project);
bool save_cost_center_blocking(cost_center cost);
bool save_tax_rate_blocking(tax_rate rate);
bool save_contact_blocking(contact c);
bool save_invoice_blocking(invoice inv);
-
- // Archiving functions.
bool save_administration_info_blocking();
bool save_all_tax_rates_blocking();
bool save_all_cost_centers_blocking();
- bool save_all_async();
-
+ bool save_activities_blocking();
} \ No newline at end of file
diff --git a/include/file_templates.hpp b/include/file_templates.hpp
index 5404270..ec78cb7 100644
--- a/include/file_templates.hpp
+++ b/include/file_templates.hpp
@@ -130,6 +130,14 @@ namespace file_template {
"<InvoiceExtras>\n"
" <Status>{{INVOICE_STATUS}}</Status>\n"
"</InvoiceExtras>\n";
+
+ static const char *activity_template =
+ "<Activity>\n"
+ " <Timestamp>{{TIMESTAMP}}</Timestamp>\n"
+ " <User>{{USERNAME}}</User>\n"
+ " <RefId>{{REF_ID}}</RefId>\n"
+ " <Message>{{MESSAGE}}</Message>\n"
+ "</Activity>\n";
static const char *peppol_invoice_template =
/*"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"*/
diff --git a/src/administration.cpp b/src/administration.cpp
index 44438ff..0b1a0db 100644
--- a/src/administration.cpp
+++ b/src/administration.cpp
@@ -1520,7 +1520,7 @@ a_err administration::invoice_update(invoice* inv)
if (invoice_changed_event_callback) invoice_changed_event_callback(c);
- administration::activity_add(ACTIVITY_USER, c->id, "activity.update_invoice", 0);
+ administration::activity_add(ACTIVITY_USER, c->id, "activity.update_invoice");
return A_ERR_SUCCESS;
}
}
@@ -1578,7 +1578,7 @@ a_err administration::invoice_add(invoice* inv)
return A_ERR_GENERIC;
}
- administration::activity_add(ACTIVITY_USER, inv->id, "activity.add_invoice", 0);
+ administration::activity_add(ACTIVITY_USER, inv->id, "activity.add_invoice");
g_administration.next_id++;
g_administration.next_sequence_number++;
@@ -1933,7 +1933,7 @@ billing_item administration::billing_item_create_empty()
// Activity functions.
// ===================
-a_err administration::activity_add(char* user, char* ref_id, char* message, ...)
+a_err administration::activity_add(char* user, char* ref_id, char* message)
{
activity* new_activity = (activity*)memops::alloc(sizeof(activity));
strops::copy(new_activity->user_name, user, MAX_LEN_SHORT_DESC);
@@ -1941,21 +1941,6 @@ a_err administration::activity_add(char* user, char* ref_id, char* message, ...)
strops::copy(new_activity->message, message, MAX_LEN_LONG_DESC);
new_activity->timestamp = time(NULL);
- va_list args;
- va_start(args, message);
-
- char* param;
- u32 param_count = 0;
- do
- {
- param = va_arg(args, char*);
- if (param != 0) {
- strops::copy(new_activity->params[param_count++], param, MAX_LEN_LONG_DESC);
- }
- } while (param && param_count < ACTIVITY_MAX_PARAMS);
-
- va_end(args);
-
if (!list_prepend(&g_administration.activities, new_activity)) {
return A_ERR_GENERIC;
}
@@ -1975,4 +1960,20 @@ u32 administration::activity_get_all_for_object(activity* buffer, char* ref_id)
list_iterator_stop(&g_administration.activities);
return write_cursor;
+}
+
+u32 administration::activity_count()
+{
+ return list_size(&g_administration.activities);
+}
+
+a_err administration::activity_get_by_index(u32 index, activity* buffer)
+{
+ assert(buffer);
+
+ activity* c = (activity *)list_get_at(&g_administration.activities, index);
+ if (c == NULL) return A_ERR_NOT_FOUND;
+ *buffer = *c;
+
+ return A_ERR_SUCCESS;
} \ No newline at end of file
diff --git a/src/administration_reader.cpp b/src/administration_reader.cpp
index 3706e72..6c7234d 100644
--- a/src/administration_reader.cpp
+++ b/src/administration_reader.cpp
@@ -70,7 +70,7 @@ bool administration_reader::open_existing(char* file_path)
continue;
}
- if (strops::equals(name, ADMIN_FILE_INFO))
+ if (strops::equals(name, ADMIN_INFO_FILE))
{
administration_reader::import_administration_info(buffer, (size_t)size);
}
diff --git a/src/administration_writer.cpp b/src/administration_writer.cpp
index 3191be7..8cd1dcf 100644
--- a/src/administration_writer.cpp
+++ b/src/administration_writer.cpp
@@ -933,7 +933,7 @@ bool administration_writer::save_administration_info_blocking()
//// Write to Disk.
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(ADMIN_FILE_INFO, file_content, final_length)) result = 0;
+ else if (!write_to_zip(ADMIN_INFO_FILE, file_content, final_length)) result = 0;
memops::unalloc(file_content);
@@ -941,4 +941,55 @@ bool administration_writer::save_administration_info_blocking()
else logger::error("Failed to save administration info.");
return result;
+}
+
+bool administration_writer::save_activities_blocking()
+{
+ STOPWATCH_START;
+
+ u32 activity_count = administration::activity_count();
+ u32 activity_list_buffer_size = (u32)strops::length(file_template::activity_template) * 3 * activity_count; // Ballpark list size. // @TODO
+ if (activity_list_buffer_size == 0) activity_list_buffer_size = 100;
+
+ char* activity_list_buffer = (char*)memops::alloc(activity_list_buffer_size);
+ memops::zero(activity_list_buffer, activity_list_buffer_size);
+ u32 activity_list_buffer_cursor = 0;
+
+ snprintf(activity_list_buffer, activity_list_buffer_size, "<ActivityList>"); // @TODO replace with strops function
+ activity_list_buffer_cursor += strlen(activity_list_buffer);
+
+ for (u32 i = 0; i < activity_count; i++)
+ {
+ activity ac;
+ a_err found = administration::activity_get_by_index(i, &ac);
+ if (found != A_ERR_SUCCESS) continue;
+
+ int buf_length = 0;
+ char* file_content = copy_template(file_template::activity_template, &buf_length);
+
+ strops::replace_int32(file_content, buf_length, "{{TIMESTAMP}}", ac.timestamp);
+ strops::replace(file_content, buf_length, "{{USERNAME}}", ac.user_name);
+ strops::replace(file_content, buf_length, "{{REF_ID}}", ac.ref_id);
+ strops::replace(file_content, buf_length, "{{MESSAGE}}", ac.message);
+
+ u32 content_len = (u32)strops::length(file_content);
+ memops::copy(activity_list_buffer+activity_list_buffer_cursor, file_content, content_len);
+
+ activity_list_buffer_cursor += content_len;
+ }
+
+ snprintf(activity_list_buffer+activity_list_buffer_cursor, activity_list_buffer_size-activity_list_buffer_cursor, "</ActivityList>");
+
+ //// Write to Disk.
+ bool result = 1;
+ int final_length = (int)strops::length(activity_list_buffer);
+ if (!xml_string_is_valid((uint8_t*)activity_list_buffer, final_length)) result = 0;
+ else if (!write_to_zip(ACTIVITY_FILE, activity_list_buffer, final_length)) result = 0;
+
+ memops::unalloc(activity_list_buffer);
+
+ if (result) logger::info("Saved activity list in %.3fms.", STOPWATCH_TIME);
+ else logger::error("Failed to save activity list.");
+
+ return result;
} \ No newline at end of file
diff --git a/src/main_linux.cpp b/src/main_linux.cpp
index 867073a..1d05aff 100644
--- a/src/main_linux.cpp
+++ b/src/main_linux.cpp
@@ -114,18 +114,14 @@ int main(int argc, char** argv)
glClearColor(clear_color.x * clear_color.w, clear_color.y * clear_color.w, clear_color.z * clear_color.w, clear_color.w);
glClear(GL_COLOR_BUFFER_BIT);
- // If you are using this code with non-legacy OpenGL header/contexts (which you should not, prefer using imgui_impl_opengl3.cpp!!),
- // you may need to backup/reset/restore other state, e.g. for current shader using the commented lines below.
- //GLint last_program;
- //glGetIntegerv(GL_CURRENT_PROGRAM, &last_program);
- //glUseProgram(0);
ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData());
- //glUseProgram(last_program);
glfwMakeContextCurrent(window);
glfwSwapBuffers(window);
}
+ administration_writer::save_activities_blocking();
+
administration_writer::destroy();
timer_lib_shutdown();
administration::destroy();
diff --git a/src/ui/ui_invoices.cpp b/src/ui/ui_invoices.cpp
index e9af66e..78e5b31 100644
--- a/src/ui/ui_invoices.cpp
+++ b/src/ui/ui_invoices.cpp
@@ -482,8 +482,8 @@ static void draw_send_options()
if (status == E_ERR_SUCCESS) {
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
+ administration::activity_add(ACTIVITY_USER, active_invoice.id, "Invoice status changed"); // @locale
+ administration::activity_add(ACTIVITY_USER, active_invoice.id, "Sent email"); // @locale
_reload_activities();
}