#include #include #include #include #include #include "log.hpp" #include "strops.hpp" #include "administration_reader.hpp" #include "administration_writer.hpp" #include "tinyfiledialogs.h" bool administration_reader_open_new() { // @localize char const * lFilterPatterns[1] = { "*.openbook" }; char* save_path = tinyfd_saveFileDialog("Select destination", NULL, 1, lFilterPatterns, NULL); if (!save_path) return false; administration_create_default(save_path); return true; } bool administration_reader_open_existing(char* file_path) { if (file_path == NULL) { // @localize char const * lFilterPatterns[1] = { "*.openbook" }; file_path = tinyfd_openFileDialog("Select save file", NULL, 1, lFilterPatterns, NULL, 0); if (!file_path) return false; } STOPWATCH_START; administration_create_from_file(file_path); zip_t* zip = zip_open(file_path, 0, 'r'); size_t i, n = zip_entries_total(zip); for (i = 0; i < n; ++i) { zip_entry_openbyindex(zip, i); { const char *name = zip_entry_name(zip); int isdir = zip_entry_isdir(zip); if (isdir) continue; unsigned long long size = zip_entry_size(zip); char* buffer = (char*)malloc(size+1); memset(buffer, 0, size+1); zip_entry_read(zip, (void**)&buffer, (size_t*)&size); if (strlen(name) == 0) continue; if (strcmp(name, ADMIN_FILE_INFO) == 0) { administration_reader_import_administration_info(buffer, (size_t)size); } else if (strops_prefix("T/", name)) { administration_reader_import_tax_bracket(buffer, (size_t)size); } else if (strops_prefix("E/", name)) { administration_reader_import_cost_center(buffer, (size_t)size); } else if (strops_prefix("P/", name)) { administration_reader_import_project(buffer, (size_t)size); } else if (strops_prefix("C/", name)) { administration_reader_import_contact(buffer, (size_t)size); } free(buffer); } zip_entry_close(zip); } zip_close(zip); log_add("Imported '%s' in %.3fms.", file_path, STOPWATCH_TIME); return true; } static s64 _get_xml_s64(xml_node* root, char* child_name) { struct xml_node* node = xml_easy_child(root, (uint8_t *)child_name, 0); char xml_content[512]; memset(xml_content, 0, 512); struct xml_string* str = xml_node_content(node); xml_string_copy(str, (uint8_t *)xml_content, xml_string_length(str)); char *endptr; long long val = strtoll(xml_content, &endptr, 10); s64 num = (int64_t) val; return num; } static s32 _get_xml_s32(xml_node* root, char* child_name) { struct xml_node* node = xml_easy_child(root, (uint8_t *)child_name, 0); char xml_content[512]; memset(xml_content, 0, 512); struct xml_string* str = xml_node_content(node); xml_string_copy(str, (uint8_t *)xml_content, xml_string_length(str)); char *endptr; long val = strtol(xml_content, &endptr, 10); s32 num = (int32_t) val; return num; } static float _get_xml_float(xml_node* root, char* child_name) { struct xml_node* node = xml_easy_child(root, (uint8_t *)child_name, 0); char xml_content[512]; memset(xml_content, 0, 512); struct xml_string* str = xml_node_content(node); xml_string_copy(str, (uint8_t *)xml_content, xml_string_length(str)); char *endptr; float val = strtof(xml_content, &endptr); return val; } static char* _get_xml_str(xml_node* root, char* buffer, size_t bufsize, char* child_name) { struct xml_node* node = xml_easy_child(root, (uint8_t *)child_name, 0); memset(buffer, 0, bufsize); struct xml_string* str = xml_node_content(node); xml_string_copy(str, (uint8_t *)buffer, xml_string_length(str)); return buffer; } bool administration_reader_import_contact(char* buffer, size_t buffer_size) { STOPWATCH_START; xml_document* document = xml_parse_document((uint8_t *)buffer, buffer_size); if (!document) return false; struct xml_node* root = xml_document_root(document); contact data; _get_xml_str(root, data.id, MAX_LEN_ID, "Id"); _get_xml_str(root, data.name, MAX_LEN_LONG_DESC, "Name"); data.type = (contact_type)_get_xml_s32(root, "Type"); _get_xml_str(root, data.taxid, MAX_LEN_TAXID, "TaxId"); _get_xml_str(root, data.businessid, MAX_LEN_BUSINESSID, "BusinessId"); _get_xml_str(root, data.email, MAX_LEN_EMAIL, "Email"); _get_xml_str(root, data.phone_number, MAX_LEN_PHONE, "PhoneNumber"); _get_xml_str(root, data.bank_account, MAX_LEN_BANK, "BankAccount"); struct xml_node* node_address = xml_easy_child(root, (uint8_t *)"Address", 0); _get_xml_str(node_address, data.address.address1, MAX_LEN_ADDRESS, "AddressLine1"); _get_xml_str(node_address, data.address.address2, MAX_LEN_ADDRESS, "AddressLine2"); _get_xml_str(node_address, data.address.country_code, MAX_LEN_COUNTRY_CODE, "CountryCode"); _get_xml_str(node_address, data.address.city, MAX_LEN_ADDRESS, "City"); _get_xml_str(node_address, data.address.postal, MAX_LEN_ADDRESS, "Postal"); _get_xml_str(node_address, data.address.region, MAX_LEN_ADDRESS, "Region"); bool result = administration_contact_import(data); log_add("Loaded contact '%s' in %.3fms.", data.name, STOPWATCH_TIME); return result; } bool administration_reader_import_project(char* buffer, size_t buffer_size) { STOPWATCH_START; xml_document* document = xml_parse_document((uint8_t *)buffer, buffer_size); if (!document) return false; struct xml_node* root = xml_document_root(document); project data; _get_xml_str(root, data.id, MAX_LEN_ID, "Id"); _get_xml_str(root, data.description, MAX_LEN_LONG_DESC, "Description"); data.state = (project_state)_get_xml_s32(root, "State"); data.start_date = _get_xml_s64(root, "StartDate"); data.end_date = _get_xml_s64(root, "EndDate"); bool result = administration_project_import(data); log_add("Loaded project in %.3fms. id=%s description=%s state=%d started=%lld end=%lld", STOPWATCH_TIME, data.id, data.description, data.state, data.start_date, data.end_date); return result; } bool administration_reader_import_cost_center(char* buffer, size_t buffer_size) { STOPWATCH_START; xml_document* document = xml_parse_document((uint8_t *)buffer, buffer_size); if (!document) return false; struct xml_node* root = xml_document_root(document); cost_center data; _get_xml_str(root, data.id, MAX_LEN_ID, "Id"); _get_xml_str(root, data.code, MAX_LEN_CODE, "Code"); _get_xml_str(root, data.description, MAX_LEN_LONG_DESC, "Description"); bool result = administration_cost_center_import(data); log_add("Loaded cost center in %.3fms. id=%s code=%s description=%s", STOPWATCH_TIME, data.id, data.code, data.description); return result; } bool administration_reader_import_tax_bracket(char* buffer, size_t buffer_size) { STOPWATCH_START; xml_document* document = xml_parse_document((uint8_t *)buffer, buffer_size); if (!document) return false; struct xml_node* root = xml_document_root(document); country_tax_bracket data; _get_xml_str(root, data.id, MAX_LEN_ID, "Id"); _get_xml_str(root, data.country_code, MAX_LEN_COUNTRY_CODE, "CountryCode"); _get_xml_str(root, data.category_code, MAX_LEN_CODE, "Category"); data.rate = _get_xml_float(root, "Rate"); bool result = administration_tax_bracket_import(data); log_add("Loaded tax bracket info in %.3fms. id=%s country_code=%s category_code=%s rate=%.2f", STOPWATCH_TIME, data.id, data.country_code, data.category_code, data.rate); return result; } bool administration_reader_import_administration_info(char* buffer, size_t buffer_size) { STOPWATCH_START; xml_document* document = xml_parse_document((uint8_t *)buffer, buffer_size); if (!document) return false; struct xml_node* root = xml_document_root(document); administration* ad = administration_get(); ad->next_id = _get_xml_s32(root, "NextId"); ad->next_sequence_number = _get_xml_s32(root, "NextSequenceNumber"); _get_xml_str(root, ad->company_info.id, MAX_LEN_ID, "CompanyInfoId"); log_add("Loaded administration info in %.3fms. next_id=%d next_sequence_number=%d company_id=%s", STOPWATCH_TIME, ad->next_id, ad->next_sequence_number, ad->company_info.id); return true; }