summaryrefslogtreecommitdiff
path: root/src/administration_writer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/administration_writer.cpp')
-rw-r--r--src/administration_writer.cpp65
1 files changed, 61 insertions, 4 deletions
diff --git a/src/administration_writer.cpp b/src/administration_writer.cpp
index f8b4302..779a5f1 100644
--- a/src/administration_writer.cpp
+++ b/src/administration_writer.cpp
@@ -229,7 +229,7 @@ bool administration_writer_save_invoice_blocking(invoice inv)
STOPWATCH_START;
bool result = 1;
- int buf_length = 150000; // Ballpark file content size.
+ int buf_length = 150000; // Ballpark file content size.
char* file_content = (char*)malloc(buf_length);
memset(file_content, 0, buf_length);
memcpy(file_content, peppol_invoice_template, strlen(peppol_invoice_template));
@@ -237,12 +237,31 @@ bool administration_writer_save_invoice_blocking(invoice inv)
struct tm *tm_info = 0;
char date_buffer[11]; // "YYYY-MM-DD" + null terminator
+ // properties not stored from invoice:
+ // - id (can be retrieved from filename)
+ // - invoice allowance (can be recalculated from billing items)
+
+ // properties not stored from supplier/customer/addressee:
+ // - type
+ // - bank account
+ // These can all be retrieved from existing contacts.
+
+ // properties not stored from billing item:
+ // - invoice_id (not necessary)
+ // - discount (can be recalculated from line_amount - (quantity * unit_price) )
+ // - tax (can be recalculated)
+ // - total (can be recalculated)
+
strops_replace(file_content, buf_length, "{{INVOICE_ID}}", inv.sequential_number);
strops_replace(file_content, buf_length, "{{CURRENCY}}", inv.currency);
+ strops_replace(file_content, buf_length, "{{PROJECT_ID}}", inv.project_id);
+ strops_replace(file_content, buf_length, "{{COST_CENTER_CODE}}", inv.cost_center_id);
+ strops_replace(file_content, buf_length, "{{INVOICE_DOCUMENT}}", inv.document);
// Supplier data
strops_replace(file_content, buf_length, "{{SUPPLIER_ENDPOINT_SCHEME}}", administration_writer_get_eas_scheme_for_address(inv.supplier.address));
strops_replace(file_content, buf_length, "{{SUPPLIER_ENDPOINT_ID}}", administration_writer_get_eas_id_for_contact(inv.supplier));
+ strops_replace(file_content, buf_length, "{{SUPPLIER_ID}}", inv.supplier.id);
strops_replace(file_content, buf_length, "{{SUPPLIER_NAME}}", inv.supplier.name);
strops_replace(file_content, buf_length, "{{SUPPLIER_STREET}}", inv.supplier.address.address1);
strops_replace(file_content, buf_length, "{{SUPPLIER_STREET2}}", inv.supplier.address.address2);
@@ -251,10 +270,15 @@ bool administration_writer_save_invoice_blocking(invoice inv)
strops_replace(file_content, buf_length, "{{SUPPLIER_REGION}}", inv.supplier.address.region);
strops_replace(file_content, buf_length, "{{SUPPLIER_COUNTRY}}", inv.supplier.address.country_code);
strops_replace(file_content, buf_length, "{{SUPPLIER_VAT_ID}}", inv.supplier.taxid);
+ strops_replace(file_content, buf_length, "{{SUPPLIER_LEGAL_NAME}}", inv.supplier.name);
+ strops_replace(file_content, buf_length, "{{SUPPLIER_BUSINESS_ID}}", inv.supplier.businessid);
+ strops_replace(file_content, buf_length, "{{SUPPLIER_PHONE_NUMBER}}", inv.supplier.phone_number);
+ strops_replace(file_content, buf_length, "{{SUPPLIER_EMAIL}}", inv.supplier.email);
// Customer data
strops_replace(file_content, buf_length, "{{CUSTOMER_ENDPOINT_SCHEME}}", administration_writer_get_eas_scheme_for_address(inv.customer.address));
strops_replace(file_content, buf_length, "{{CUSTOMER_ENDPOINT_ID}}", administration_writer_get_eas_id_for_contact(inv.customer));
+ strops_replace(file_content, buf_length, "{{CUSTOMER_ID}}", inv.customer.id);
strops_replace(file_content, buf_length, "{{CUSTOMER_NAME}}", inv.customer.name);
strops_replace(file_content, buf_length, "{{CUSTOMER_STREET}}", inv.customer.address.address1);
strops_replace(file_content, buf_length, "{{CUSTOMER_STREET2}}", inv.customer.address.address2);
@@ -263,6 +287,22 @@ bool administration_writer_save_invoice_blocking(invoice inv)
strops_replace(file_content, buf_length, "{{CUSTOMER_REGION}}", inv.customer.address.region);
strops_replace(file_content, buf_length, "{{CUSTOMER_COUNTRY}}", inv.customer.address.country_code);
strops_replace(file_content, buf_length, "{{CUSTOMER_VAT_ID}}", inv.customer.taxid);
+ strops_replace(file_content, buf_length, "{{CUSTOMER_LEGAL_NAME}}", inv.customer.name);
+ strops_replace(file_content, buf_length, "{{CUSTOMER_BUSINESS_ID}}", inv.customer.businessid);
+ strops_replace(file_content, buf_length, "{{CUSTOMER_PHONE_NUMBER}}", inv.customer.phone_number);
+ strops_replace(file_content, buf_length, "{{CUSTOMER_EMAIL}}", inv.customer.email);
+
+ // Delivery data
+ tm_info = localtime(&inv.delivered_at);
+ strftime(date_buffer, sizeof(date_buffer), "%Y-%m-%d", tm_info);
+ strops_replace(file_content, buf_length, "{{DELIVERY_DATE}}", date_buffer);
+ strops_replace(file_content, buf_length, "{{DELIVERY_NAME}}", inv.addressee.name);
+ strops_replace(file_content, buf_length, "{{DELIVERY_STREET}}", inv.addressee.address.address1);
+ strops_replace(file_content, buf_length, "{{DELIVERY_STREET2}}", inv.addressee.address.address2);
+ strops_replace(file_content, buf_length, "{{DELIVERY_CITY}}", inv.addressee.address.city);
+ strops_replace(file_content, buf_length, "{{DELIVERY_POSTAL}}", inv.addressee.address.postal);
+ strops_replace(file_content, buf_length, "{{DELIVERY_REGION}}", inv.addressee.address.region);
+ strops_replace(file_content, buf_length, "{{DELIVERY_COUNTRY}}", inv.addressee.address.country_code);
// Payment means
strops_replace_int32(file_content, buf_length, "{{PAYMENT_TYPE}}", inv.payment_means.payment_method);
@@ -270,7 +310,7 @@ bool administration_writer_save_invoice_blocking(invoice inv)
strops_replace(file_content, buf_length, "{{SUPPLIER_BIC}}", inv.payment_means.service_provider_id);
// Tax breakdown
- strops_replace_float(file_content, buf_length, "{{TOTAL_TAX_AMOUNT}}", inv.total, 2);
+ strops_replace_float(file_content, buf_length, "{{TOTAL_TAX_AMOUNT}}", inv.tax, 2);
{ // Create tax subtotal list.
country_tax_bracket* tax_bracket_buffer = (country_tax_bracket*)malloc(sizeof(country_tax_bracket)*administration_billing_item_count(&inv));
u32 tax_bracket_count = administration_invoice_get_tax_brackets(&inv, tax_bracket_buffer);
@@ -337,10 +377,23 @@ bool administration_writer_save_invoice_blocking(invoice inv)
strops_replace(billing_item_file_content, billing_item_buf_length, "{{ITEM_NAME}}", bi.description);
strops_replace(billing_item_file_content, billing_item_buf_length, "{{LINE_TAX_CATEGORY}}", bracket.category_code);
strops_replace_float(billing_item_file_content, billing_item_buf_length, "{{LINE_TAX_PERCENT}}", bracket.rate, 2);
- strops_replace_float(billing_item_file_content, billing_item_buf_length, "{{LINE_AMOUNT}}", bi.net, 2);
+ strops_replace_float(billing_item_file_content, billing_item_buf_length, "{{LINE_AMOUNT}}", bi.net, 2); // line amount = net_per_item * items_count - discount
strops_replace_float(billing_item_file_content, billing_item_buf_length, "{{QUANTITY}}", bi.amount, 2);
- strops_replace_float(billing_item_file_content, billing_item_buf_length, "{{UNIT_PRICE}}", bi.net_per_item, 2);
+ strops_replace_float(billing_item_file_content, billing_item_buf_length, "{{UNIT_PRICE}}", bi.net_per_item, 2); // unit price before discount
strops_replace(billing_item_file_content, billing_item_buf_length, "{{UNIT_CODE}}", bi.amount_is_percentage ? "%" : "X");
+ strops_replace(billing_item_file_content, billing_item_buf_length, "{{TAX_BRACKET_ID}}", bi.tax_bracket_id);
+
+ if (bi.discount_is_percentage) {
+ strops_replace(billing_item_file_content, billing_item_buf_length, "{{ALLOWANCE_IS_PERCENTAGE}}",
+ "<cbc:MultiplierFactorNumeric>{{DISCOUNT_TOTAL_PERCENTAGE}}</cbc:MultiplierFactorNumeric>");
+ strops_replace_float(billing_item_file_content, billing_item_buf_length, "{{DISCOUNT_TOTAL_PERCENTAGE}}", bi.allowance / (bi.net + bi.allowance), 2);
+ }
+ else {
+ strops_replace(billing_item_file_content, billing_item_buf_length, "{{ALLOWANCE_IS_PERCENTAGE}}", "");
+ }
+
+ strops_replace_float(billing_item_file_content, billing_item_buf_length, "{{DISCOUNT_TOTAL}}", bi.allowance, 2);
+ strops_replace_float(billing_item_file_content, billing_item_buf_length, "{{DISCOUNT_BASE_AMOUNT}}", bi.net + bi.allowance, 2); // Total net before discount.
u32 content_len = (u32)strlen(billing_item_file_content);
memcpy(billing_item_list_buffer+billing_item_list_buffer_cursor, billing_item_file_content, content_len);
@@ -360,6 +413,10 @@ bool administration_writer_save_invoice_blocking(invoice inv)
strftime(date_buffer, sizeof(date_buffer), "%Y-%m-%d", tm_info);
strops_replace(file_content, buf_length, "{{ISSUE_DATE}}", date_buffer);
+ tm_info = localtime(&inv.expires_at);
+ strftime(date_buffer, sizeof(date_buffer), "%Y-%m-%d", tm_info);
+ strops_replace(file_content, buf_length, "{{DUE_DATE}}", date_buffer);
+
//// Write to Disk.
char final_path[50];
snprintf(final_path, 50, "%s.xml", inv.id);