Skip to content

Instantly share code, notes, and snippets.

@schakko
Last active November 17, 2023 09:05
Show Gist options
  • Save schakko/21b20fa56d63d18b7a2d7f009c159916 to your computer and use it in GitHub Desktop.
Save schakko/21b20fa56d63d18b7a2d7f009c159916 to your computer and use it in GitHub Desktop.
Fix WooCommerce Germanized invoices due to changes or inconsistent order data

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_items by loading the data from woocommerce_order_items
  • Fill up the invoice meta data in table storeabill_document_itemmeta by loading the data from woocommerce_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 the Sync button in the WooCommerce order UI, the process is repeated. For sake of sanity, do not manipulate any of the the storeabill_document_item* tables but instead fix the data in woocommerce_order_items.

1. Addresses

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.

2. Missing tax rate OR Difference in tax rates between original invoice date and today

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';

3. Create invoice draft

Now you should be able to generate a new invoice draft by clicking onto the Create invoice button. Do not finalize yet.

4. Customize invoice date

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_id GET parameter.
  • Add the following code to a functions.php in your wp-content/plugins folder:
    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 ) in Vendidero\StoreaBill\Invoice\Invoice.php and resets the invoice date, before rendering the PDF.

5. Bonus: Manipulate the invoice with custom tax rate

⚠️ You do not want to do this. Fix the data in woocommerce_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}';
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment