Extending the plugin
The plugin exposes several hooks that allow you to add/modify functionality through WordPress filters. This page lists the available filters and provides example code for some common use cases.
List of available filter hooks
Placeholders
Some hooks contain placeholder {{doctype}}
, the value of which is either invoice
or estimate
, depending on the type of Moneybird document that is being generated. Document type estimate
is only available in version 4.0 and newer.
woocommerce_moneybird_combined_invoice_order_heading
Filter the order heading text on combined invoices (i.e. invoices with multiple orders). Default is "*Order {{order_id}}*". The heading is skipped if the filter returns an empty string. - Plugin versions: 5.6.0 and newer Filtered object: String containing the heading text. Arguments: (1) WC_Order
woocommerce_moneybird_contact_details
Filter array containing the contact details of a given order. These contact details are used to search for a match in the Moneybird contacts, or to create a new Moneybird contact. - Plugin versions: 3.5.0 and newer Filtered object: Array containing the contact details Arguments: (1) WC_Order
woocommerce_moneybird_contact_updatable
Filter a boolean indicating whether a given existing Moneybird contact may be updated. - Plugin versions: 3.51.0 and newer Filtered object: Boolean indicating update permission Arguments: (1) Moneybird contact object
woocommerce_moneybird_credit_invoice
Filter the credit invoice object before it is pushed to Moneybird. - Plugin versions: 3.0.0 and newer Filtered object: Array containing the complete credit invoice object Arguments: (1) WC_Order: refund object, (2) WC_Order: original order
woocommerce_moneybird_custom_field_value
Filter the value of a custom field. - Plugin versions: 3.20.0 and newer Filtered object: Value of the custom field for the corresponding WC_Order. Arguments: (1) string: custom field key, (2) int: order id
woocommerce_moneybird_custom_fields
Filter the array of available custom field keys. - Plugin versions: 3.20.0 and newer Filtered object: Array containing the available custom field keys. Arguments: None
woocommerce_moneybird_{{doctype}}
Filter the sales invoice or estimate object before it is submitted to Moneybird. - Plugin versions: 2.1.2 and newer Filtered object: Array containing the complete invoice/estimate object Arguments: (1) WC_Order, (2) Array of secondary WC_Orders (in case of combined invoice)
woocommerce_moneybird_invoice_coupons
Filter invoice lines corresponding to coupon redemptions. - Plugin versions: 3.56 and newer Filtered object: Array of invoice lines (see source for details) Arguments: (1) WC_Order
woocommerce_moneybird_invoice_item
Filter item details that are put on the Moneybird invoice. Return an empty array to skip the item. - Plugin versions: 2.5 and newer Filtered object: Array of invoice lines (see source for details) Arguments: (1) WC_Order_Item, (2) WC_Order
woocommerce_moneybird_invoice_shipping
Filter invoice lines corresponding to shipping costs. - Plugin versions: 2.5 and newer Filtered object: Array of invoice lines (see source for details) Arguments: (1) WC_Order
woocommerce_moneybird_invoice_fees
Filter invoice lines corresponding to ordering fees. - Plugin versions: 2.5 and newer Filtered object: Array of invoice lines (see source for details) Arguments: (1) WC_Order
woocommerce_moneybird_invoice_gift_cards
Filter invoice lines corresponding to gift card redemptions. - Plugin versions: 3.49 and newer Filtered object: Array of invoice lines (see source for details) Arguments: (1) WC_Order
woocommerce_moneybird_invoice_payments
Filter the array of invoice payments that are submitted to Moneybird for a given WC_Order. - Plugin versions: 5.8.0 and newer Filtered object: Array of payment data arrays. Arguments: (1) WC_Order, (2) Moneybird invoice object.
woocommerce_moneybird_{{doctype}}_send_parameters
Filter the parameters of the Moneybird API request to send an invoice or estimate. - Plugin versions: 3.48.0 and newer Filtered object: Array containing the API request parameters Arguments: (1) WC_Order, (2) Moneybird invoice/estimate object
woocommerce_moneybird_{{doctype}}_sequence_id
Filter the `{id}` part of the invoice/estimate number, usually in format `{year}-{id}`. The default is empty, causing Moneybird to automatically generate the sequence id upon sending. - Plugin versions: 2.1.1 and newer Filtered object: incremental part of the invoice/estimate id Arguments: (1) WC_Order
woocommerce_moneybird_is_order_paid
Filter the payment status of an order. By default, an order is considered paid if the status is "processing" or "complete", and a payment method has been associated with the order. - Plugin versions: 2.5 and newer Filtered object: Boolean indicating the payment status Arguments: (1) WC_Order, (2) Array of secondary WC_Orders (in case of combined invoice)
woocommerce_moneybird_new_contact
Filter array containing the fields for a new Moneybird contact. Use this filter to add any additional fields, such as `tax_number`. - Plugin versions: 2.1.1 and newer Filtered object: Array containing the contact details Arguments: (1) WC_Order
woocommerce_moneybird_process_order
Filter a boolean indicating whether the specified order should be processed. Returning false allows one to suppress Moneybird contact and invoice generation. - Plugin versions: 3.34.0 and newer Filtered object: Boolean indicating whether order should be processed (default: true). Arguments: (1) WC_Order, (2) string: either 'invoice' or 'estimate'
woocommerce_moneybird_reference
Filter the value of the reference field on the invoice. - Plugin versions: 2.1.1 and newer Filtered object: Value of the invoice reference string, for example "order #{{order_id}}" Arguments: (1) WC_Order, (2) Array of secondary WC_Orders (in case of combined invoice)
woocommerce_moneybird_register_payment
Filter a boolean indicating whether to register a payment in Moneybird. Use this filter to overwrite the payment registration setting for individual orders. - Plugin versions: 2.1.2 and newer Filtered object: Boolean indicating if the order payment should be registered in Moneybird Arguments: (1) WC_Order
woocommerce_moneybird_revenue_ledger_accounts
Filter the array of available Moneybird revenue ledger accounts. The keys of the associative array start with 's', followed by the id of the ledger account. The values contain the ledger names. - Plugin versions: 3.16.0 and newer Filtered object: Associative array containing the available Moneybird ledger accounts. Arguments: (1) Array: in format s{id} => {ledger_name}.
woocommerce_moneybird_payment_amount
Filter the payment amount. The default payment amount is equal to the open balance of the invoice (to prevent rounding errors). - Plugin versions: 2.7 and newer Filtered object: Float: payment amount in the store's default currency Arguments: (1) WC_Order
woocommerce_moneybird_prices_include_tax
Filter a boolean indicating whether the prices on the Moneybird document should be specified inclusive of tax. The default is to follow the WooCommerce setting for specifying prices inclusive/exclusive of tax. Deviating from this can lead to rounding errors. - Plugin versions: 3.54.0 and newer Filtered object: Boolean indicating whether prices should be specified inclusive of tax. Arguments: (1) WC_Order, (2) Array of secondary WC_Orders (in case of combined invoice)
woocommerce_moneybird_sendmode
Filter the invoice sending mode. - Plugin versions: 3.3.0 and newer Filtered object: String with possible values: 'draft', 'default', 'Manual', 'Email' or 'Simplerinvoicing'. Arguments: (1) WC_Order, (2) Moneybird document (invoice or estimate).
List of available action hooks
woocommerce_moneybird_after_{{doctype}}_generate
This action is executed after a Moneybird invoice or estimate has been generated. - Plugin versions: 3.44.0 and newer Arguments: (1) WC_Order instance, (2) Moneybird invoice or estimate object, (3) Array of secondary WC_Orders (in case of combined invoice)
woocommerce_moneybird_generate_{{doctype}}_error
This action is executed if an error occurs during Moneybird document generation. It can be used for example to send a notification to the admin. - Plugin versions: 3.1.3 and newer Arguments: (1) WC_Order instance, (2) string: description of the error
woocommerce_moneybird_webhook
```txt This action is executed if the webhook is called by Moneybird. A list of all possible events that can trigger a webhook is available here: https://developer.moneybird.com/webhooks/#events
The plugin registers a webhook for the following events: administration_removed, administration_suspended, document_style_destroyed, ledger_account_deactivated, ledger_account_destroyed, project_archived, project_destroyed, sales_invoice_destroyed, sales_invoice_merged, sales_invoice_state_changed_to_paid, tax_rate_deactivated,
tax_rate_destroyed, workflow_deactivated, workflow_destroyed.
Plugin versions: 5.5.0 and newer Arguments: (1) object: webhook payload, (2) WC_MoneyBird2 instance ```
woocommerce_moneybird_webhook_{{event}}
Same as woocommerce_moneybird_webhook but with the event code included. - Plugin versions: 5.5.0 and newer Arguments: (1) object: webhook payload, (2) WC_MoneyBird2 instance
Access invoice from front-end
If you want to provide customers with a link to their invoice(s) you can use the following code to access the invoice linked to a WooCommerce order:
$moneybird = WCMB(); // This loads the registered WC_MoneyBird2 instance
$invoice = $moneybird->get_invoice_from_order_id($order_id);
if ($invoice) {
var_dump($invoice); // Replace this with code to output info about the invoice
}
Add VAT number to Moneybird contacts
Support for the EU VAT numbers plugin is built-in since v2.5.9
. The plugin checks the following order meta fields for a VAT number: _vat_number
, vat_number
, _billing_vat_number
. If one of these fields contains a VAT number, it is automatically passed to Moneybird. Almost all EU VAT plugins store the VAT number in one of the mentioned fields, so it should work out-of-the-box.
However, some custom code might be required to pass VAT numbers to Moneybird if you use another plugin to collect the VAT number.
You can add a piece of code to functions.php
such that the VAT numbers of customers get passed on to Moneybird. Modify the code below to read the VAT number from the correct location (depends on the plugin used for collecting the VAT number). It is also possible the pass the Chamber of Commerce registration (“KvK nummer” in Dutch) to Moneybird (see the commented line in the example code).
function filter_woocommerce_moneybird_new_contact($contact, $order) {
// Add VAT number from "EU VAT Number" plugin to Moneybird contact
$order_id = is_callable(array($order, 'get_id')) ? $order->get_id() : $order->id;
$vat_number = get_post_meta($order_id, '_vat_number', true); // Modify to read the correct field
if ($vat_number) {
$contact['tax_number'] = $vat_number;
}
// $contact['chamber_of_commerce'] = 'FILL THIS FIELD IF NEEDED';
return $contact;
}
add_filter('woocommerce_moneybird_new_contact', 'filter_woocommerce_moneybird_new_contact', 10, 2);
Example: order-dependent invoice workflow
Edit and paste the following code snippet in functions.php
to make the workflow of the invoice dependent on the properties of the WooCommerce order. For example, we can use a different workflow for orders in the German language:
// The following filter modifies the invoice workflow based on the WooCommerce order.
// $order contains the WC_Order instance corresponding to the order for which the invoice is being generated.
function filter_woocommerce_moneybird_modify_workflow($invoice, $order) {
// Use the $order object here to look up the required information
$order_id = is_callable(array($order, 'get_id')) ? $order->get_id() : $order->id;
$language = get_post_meta($order_id, 'wpml_language', true);
if ($language == 'de') {
// Note: the workflow id can be extracted from the url when editing it in Moneybird.
$invoice['workflow_id'] = '136261670020318887';
}
return $invoice;
}
add_filter('woocommerce_moneybird_invoice', 'filter_woocommerce_moneybird_modify_workflow', 10, 2);
Example: ignore non-virtual products when generating invoices
The code snippet below provides an example of how to filter order items when generating an invoice.
function mb_invoice_item_filter($item, $wc_order_item, $wc_order) {
// Ignore non-virtual products when generating invoices
$product = apply_filters('woocommerce_order_item_product', $wc_order->get_product_from_item($wc_order_item), $wc_order_item);
if (!$product->is_virtual()) {
$item = array();
}
return $item;
}
add_filter('woocommerce_moneybird_invoice_item', 'mb_invoice_item_filter', 10, 3);
Example: add Subscription properties as custom fields
If you use WooCommerce Subscriptions, you might want to make certain properties of subscriptions available as custom fields, so they can be mapped to custom invoice/contact fields (“Extra Velden”) in Moneybird. The following example code illustrates how this can be achieved.
function insert_subscription_custom_fields($custom_fields) {
// Add user-defined custom field keys to the list of available custom fields.
$custom_fields[] = 'subscription_start_date';
return $custom_fields;
}
add_filter('woocommerce_moneybird_custom_fields', 'insert_subscription_custom_fields', 10, 1);
function resolve_subscription_custom_field_values($val, $key, $order_id) {
// Resolve the value of all user-defined custom fields (as specified in `insert_subscription_custom_fields`).
if (!in_array($key, array('subscription_start_date'))) {
// We don't have to resolve this custom field
return $val;
}
// Get subscriptions associated with the order
$subscriptions = wcs_get_subscriptions_for_order($order_id);
if (!$subscriptions) {
$subscriptions = wcs_get_subscriptions_for_renewal_order($order_id);
}
if ($subscriptions) {
if ($key == 'subscription_start_date') {
foreach ($subscriptions as $subscription) {
$start_date = $subscription->get_time('date_created');
if ($start_date) {
$val = date('d-m-Y', $start_date);
break;
}
}
}
}
return $val;
}
add_filter('woocommerce_moneybird_custom_field_value', 'resolve_subscription_custom_field_values', 10, 3);
Example: change ledger account based on country
Use the following example code to change the Moneybird revenue ledger account (omzetcategorie) for all invoice lines if the country of the buyer is not NL.
function filter_woocommerce_moneybird_modify_ledger_account($invoice, $order) {
// Use the $order object here to look up the required information
if (strtolower($order->get_billing_country()) != 'nl') {
// Note: the ledger account id can be extracted from the url when editing it in Moneybird.
for ($i=0; $i<count($invoice['details_attributes']); $i++) {
$invoice['details_attributes'][$i]['ledger_account_id'] = '123456789'; # TODO: use correct id here
}
}
return $invoice;
}
add_filter('woocommerce_moneybird_invoice', 'filter_woocommerce_moneybird_modify_ledger_account', 10, 2);
Example: modify contact details
The following example code replaces the default values of contact fields with order meta field values.
Additionally, you can fill contact fields that are not filled by default. In the example, the “T.a.v. facturen” field is filled, corresponding to the send_invoices_to_attention
field in the Moneybird API. Refer to the Moneybird Contacts API documentation for a full overview of the available fields.
function wc_mb_modify_contact_details($contact_details, $order) {
// Replace values in $contact_details array with values from custom meta fields
// This overwrites the default field values. To clear a value, use:
// $contact_details['firstname'] = ''; // Empty value
$order_id = $order->get_id();
$contact_details['company_name'] = get_post_meta($order_id, '_custom_field_name', true);
$contact_details['firstname'] = get_post_meta($order_id, '_custom_field_name', true);
$contact_details['lastname'] = get_post_meta($order_id, '_custom_field_name', true);
$contact_details['address1'] = get_post_meta($order_id, '_custom_field_name', true);
$contact_details['address2'] = get_post_meta($order_id, '_custom_field_name', true);
$contact_details['zipcode'] = get_post_meta($order_id, '_custom_field_name', true);
$contact_details['city'] = get_post_meta($order_id, '_custom_field_name', true);
$contact_details['country'] = get_post_meta($order_id, '_custom_field_name', true);
$contact_details['email'] = get_post_meta($order_id, '_custom_field_name', true);
$contact_details['phone'] = get_post_meta($order_id, '_custom_field_name', true);
// Fill the "T.a.v. facturen" field of Moneybird contact
$contact_details['send_invoices_to_attention'] = get_post_meta($order_id, '_custom_field_name', true);
return $contact_details;
}
add_filter('woocommerce_moneybird_contact_details', 'wc_mb_modify_contact_details', 10, 2);
Example: force prices on invoice to be inclusive/exclusive of tax
The plugin follows the WooCommerce setting for prices being inclusive of exclusive of tax. If product prices are inclusive of tax, the invoice will also have invoice lines inclusive of tax and vice versa.
Code to force the invoice prices to be exclusive of tax:
// The following filter forces the invoice to have prices EXCLUSIVE of tax.
function force_moneybird_prices_exclude_tax($include_tax, $order) {
return false;
}
add_filter('woocommerce_moneybird_prices_include_tax', 'force_moneybird_prices_exclude_tax', 10, 2);
Code to force the invoice prices to be inclusive of tax:
// The following filter forces the invoice to have prices INCLUSIVE of tax.
function force_moneybird_prices_include_tax($include_tax, $order) {
return true;
}
add_filter('woocommerce_moneybird_prices_include_tax', 'force_moneybird_prices_include_tax', 10, 2);
Example: include product properties on invoice line
A WooCommerce product can have custom properties, for example “Height” or “Course date”. Such product properties are not saved in the Order, and will not be included on invoices by default. You can use the following code to add all textual product properties that are visible on the product page to the corresponding invoice line.
function wcmb_insert_product_properties($invoice_item, $item, $order) {
$product = apply_filters('woocommerce_order_item_product', $order->get_product_from_item($item), $item);
if (!$product) {
// Corresponding product is not available
return $invoice_item;
}
foreach ($product->get_attributes() as $attr_code => $attr) {
// Only include text properties that are marked as "visible on product page"
if ($attr->get_visible() && !($attr->is_taxonomy())) {
$values = array();
foreach ($attr->get_options() as $val) {
if (is_string($val) && !empty($val)) {
$values[] = $val;
}
}
if ($values) {
// Add the following to the invoice item description: white line, property name in bold, property value on separate line(s)
$invoice_item['description'] .= "\n\n*" . $attr->get_name() . "*:\n" . strip_tags(implode("\n", $values));
}
}
}
return $invoice_item;
}
add_filter('woocommerce_moneybird_invoice_item', 'wcmb_insert_product_properties', 10, 3);