When using WooCommerce Germanized you might end up with processed orders but the invoices can not be generated. Clicking onto the Create invoice button throws the following error:
An invoice could not be created due to changes to or inconsistent order data. Please review the corresponding order.
For debugging purposes, you can look into wp-content/plugins/woocommerce-germanized-pro/packages/storeabill/src/WooCommerce/Order.php. Somewhere in protected function get_order_items_to_cancel( $args = array() ) WooCommerce Germanized detects a pricing difference.
This is most likely to a mismatch between the data provided during the payment and the current point in time.
WooCommerce Germanize does the following:
- If not present, create a new invoice in the table
storeabill_documents - Fill up the invoice items in table
storeabill_document_itemsby loading the data fromwoocommerce_order_items - Fill up the invoice meta data in table
storeabill_document_itemmetaby loading the data fromwoocommerce_order_itemmeta - Check, if the generated invoice has the same sum for each of the line items
- If the invoice does not match the order, the invoice is automatically deleted.
⚠️ As soon as you click theSyncbutton in the WooCommerce order UI, the process is repeated. For sake of sanity, do not manipulate any of the thestoreabill_document_item*tables but instead fix the data inwoocommerce_order_items.
Check that the taxes are calculated properly. Copy the Billing Address to the Shipping Address field by using Copy billing address. WooCommerce Germanized might use the Shipping Address to calculate the total taxes. This might differ between the order time and the time of the creation of the invoice.
In case of a tax rate change between the original invoice date and today (e.g. if your state has changed the tax rate from 16% to 19%), update the database:
-- find order_item_id containing the order_item_type = tax; ${ORDER_ID} can be extracted from the `post` GET parameter
SELECT * FROM woocommerce_order_items WHERE order_id = ${ORDER_ID} AND order_item_type = 'tax';
-- check if the the meta_key = 'rate_percent' matches the official tax rate at tha point in time during invoice/payment creation
SELECT * FROM woocommerce_order_itemmeta WHERE order_item_id = ${ORDER_ITEM_ID} AND meta_key = 'rate_percent'
-- set correct tax rate
UPDATE woocommerce_order_itemmeta SET meta_value = 16 WHERE order_item_id = ${ORDER_ITEM_ID} AND meta_key = 'rate_percent';Now you should be able to generate a new invoice draft by clicking onto the Create invoice button. Do not finalize yet.
If the invoice date is in the past, you have to apply a WordPress hook. Otherwise, the invoice gets the current date as invoice date. Due to WooCommerce Germanized architecture it is not sufficient to just modify a database entry.
- Get the invoice document ID by hovering over the Preview button and note the
document_idGET parameter. - Add the following code to a
functions.phpin yourwp-content/pluginsfolder:add_action('storeabill_invoice_before_finalize', function($invoice) { if ($invoice->get_id() == '${DOCUMENT_ID}') { // change to the date you want $invoice->set_date_created('2021-12-03 15:00:00'); } }, 10, 1);
- The hook then gets called by
public function finalize( $defer_render = false )inVendidero\StoreaBill\Invoice\Invoice.phpand resets the invoice date, before rendering the PDF.
⚠️ You do not want to do this. Fix the data inwoocommerce_order_items. Really. The values get overwritten as soon as a new invoice for the order (or subscription) is generated. :warning I've added the script so that I do not try to be smart again.
Create a new invoice. It is automatically called Draft ${DRAFT_NUMBER}. You can manipulate the draft state by executing the following SQL script.
UPDATE adi_storeabill_documentmeta
SET meta_value = 'no'
WHERE
meta_key = '_is_reverse_charge'
AND storeabill_document_id = '${DRAFT_NUMBER}';
UPDATE adi_storeabill_documentmeta
SET meta_value = 'yes'
WHERE
meta_key = '_is_taxable'
AND storeabill_document_id = '${DRAFT_NUMBER}';
UPDATE adi_storeabill_documentmeta
SET meta_value = '${PRICE_INCLUDING_TAXES}'
WHERE
meta_key = '_total'
AND storeabill_document_id = '${DRAFT_NUMBER}';
UPDATE adi_storeabill_documentmeta
SET meta_value = '${PRICE_INCLUDING_TAXES}'
WHERE
meta_key = '_subtotal'
AND storeabill_document_id = '${DRAFT_NUMBER}';
UPDATE adi_storeabill_documentmeta
SET meta_value = '${PRICE_INCLUDING_TAXES}'
WHERE
meta_key = '_total_paid'
AND storeabill_document_id = '${DRAFT_NUMBER}';
UPDATE adi_storeabill_documentmeta
SET meta_value = '${PRICE_INCLUDING_TAXES}'
WHERE
meta_key = '_product_total'
AND storeabill_document_id = '${DRAFT_NUMBER}';
UPDATE adi_storeabill_documentmeta
SET meta_value = '${PRICE_INCLUDING_TAXES}'
WHERE
meta_key = '_product_subtotal'
AND storeabill_document_id = '${DRAFT_NUMBER}';
UPDATE adi_storeabill_documentmeta
SET meta_value = '${ONLY_TAX_AMOUNT}'
WHERE
meta_key = '_total_tax'
AND storeabill_document_id = '${DRAFT_NUMBER}';
UPDATE adi_storeabill_documentmeta
SET meta_value = '${ONLY_TAX_AMOUNT}'
WHERE
meta_key = '_product_tax'
AND storeabill_document_id = '${DRAFT_NUMBER}';
UPDATE adi_storeabill_documentmeta
SET meta_value = '${ONLY_TAX_AMOUNT}'
WHERE
meta_key = '_subtotal_tax'
AND storeabill_document_id = '${DRAFT_NUMBER}';
UPDATE adi_storeabill_documentmeta
SET meta_value = '${ONLY_TAX_AMOUNT}'
WHERE
meta_key = '_product_subtotal_tax'
AND storeabill_document_id = '${DRAFT_NUMBER}';