mirror of
https://hk.gh-proxy.com/https://github.com/pronamic/woocommerce-eu-vat-number.git
synced 2025-10-03 23:51:03 +08:00
Updates to 2.8.8
This commit is contained in:
parent
5c650eed2c
commit
651aba7531
46 changed files with 5974 additions and 5818 deletions
8
.github/scripts/release.php
vendored
8
.github/scripts/release.php
vendored
|
@ -132,14 +132,14 @@ $zip_url = $update_data->package;
|
|||
|
||||
line(
|
||||
sprintf(
|
||||
'WooCommerce Subscriptions Version: %s',
|
||||
'WooCommerce EU VAT Number Version: %s',
|
||||
$version
|
||||
)
|
||||
);
|
||||
|
||||
line(
|
||||
sprintf(
|
||||
'WooCommerce Subscriptions ZIP URL: %s',
|
||||
'WooCommerce EU VAT Number ZIP URL: %s',
|
||||
$zip_url
|
||||
)
|
||||
);
|
||||
|
@ -161,9 +161,9 @@ $plugins_dir = $work_dir . '/plugins';
|
|||
mkdir( $archives_dir );
|
||||
mkdir( $plugins_dir );
|
||||
|
||||
$plugin_dir = $plugins_dir . '/woocommerce-subscriptions';
|
||||
$plugin_dir = $plugins_dir . '/woocommerce-eu-vat-number';
|
||||
|
||||
$zip_file = $archives_dir . '/woocommerce-subscriptions-' . $version . '.zip';
|
||||
$zip_file = $archives_dir . '/woocommerce-eu-vat-number-' . $version . '.zip';
|
||||
|
||||
/**
|
||||
* Download ZIP.
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
#wc_eu_vat .inside {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
#wc_eu_vat p {
|
||||
margin: 12px !important;
|
||||
}
|
||||
.wc-eu-vat-table {
|
||||
width: 100%;
|
||||
margin: 5px 0;
|
||||
}
|
||||
.wc-eu-vat-table th, .wc-eu-vat-table td {
|
||||
text-align: left;
|
||||
padding: 7px 12px;
|
||||
}
|
||||
.eu-vat-overview {
|
||||
margin: 0;
|
||||
}
|
||||
.column-eu_vat {
|
||||
width: 10%;
|
||||
color: #555;
|
||||
}
|
||||
.column-eu_vat ul li {
|
||||
color: #555;
|
||||
#wc_eu_vat .inside {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
#wc_eu_vat p {
|
||||
margin: 12px !important;
|
||||
}
|
||||
.wc-eu-vat-table {
|
||||
width: 100%;
|
||||
margin: 5px 0;
|
||||
}
|
||||
.wc-eu-vat-table th, .wc-eu-vat-table td {
|
||||
text-align: left;
|
||||
padding: 7px 12px;
|
||||
}
|
||||
.eu-vat-overview {
|
||||
margin: 0;
|
||||
}
|
||||
.column-eu_vat {
|
||||
width: 10%;
|
||||
color: #555;
|
||||
}
|
||||
.column-eu_vat ul li {
|
||||
color: #555;
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
( function( $ ) {
|
||||
$(document.body).on( 'order-totals-recalculate-before', function( e, data ) {
|
||||
if( data && $( '#_billing_vat_number' ).length ) {
|
||||
data._billing_vat_number = $( '#_billing_vat_number' ).val();
|
||||
data._billing_country = $( '#_billing_country' ).val();
|
||||
data._shipping_country = $( '#_shipping_country' ).val();
|
||||
data._billing_postcode = $( '#_billing_postcode' ).val();
|
||||
}
|
||||
});
|
||||
}( jQuery ) );
|
||||
( function( $ ) {
|
||||
$(document.body).on( 'order-totals-recalculate-before', function( e, data ) {
|
||||
if( data && $( '#_billing_vat_number' ).length ) {
|
||||
data._billing_vat_number = $( '#_billing_vat_number' ).val();
|
||||
data._billing_country = $( '#_billing_country' ).val();
|
||||
data._shipping_country = $( '#_shipping_country' ).val();
|
||||
data._billing_postcode = $( '#_billing_postcode' ).val();
|
||||
}
|
||||
});
|
||||
}( jQuery ) );
|
||||
|
|
|
@ -1,74 +1,74 @@
|
|||
jQuery(function(){
|
||||
function field_is_required( field, is_required ) {
|
||||
if ( is_required ) {
|
||||
field.find( 'label .optional' ).remove();
|
||||
field.addClass( 'validate-required' );
|
||||
|
||||
if ( field.find( 'label .required' ).length === 0 ) {
|
||||
field.find( 'label' ).append(
|
||||
' <abbr class="required" title="' +
|
||||
wc_address_i18n_params.i18n_required_text +
|
||||
'">*</abbr>'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
field.find( 'label .required' ).remove();
|
||||
field.removeClass( 'validate-required woocommerce-invalid woocommerce-invalid-required-field' );
|
||||
|
||||
if ( field.find( 'label .optional' ).length === 0 ) {
|
||||
field.find( 'label' ).append( ' <span class="optional">(' + wc_address_i18n_params.i18n_optional_text + ')</span>' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jQuery( 'form.checkout, form#order_review').on( 'change', '#billing_country', function() {
|
||||
var country = jQuery( '#billing_country' ).val();
|
||||
var check_countries = wc_eu_vat_params.eu_countries;
|
||||
var b2b_enabled = wc_eu_vat_params.b2b_required;
|
||||
|
||||
field_is_required( jQuery( '#woocommerce_eu_vat_number_field' ), false );
|
||||
|
||||
if ( country && jQuery.inArray( country, check_countries ) >= 0 ) {
|
||||
jQuery( '#woocommerce_eu_vat_number_field' ).fadeIn();
|
||||
if ( 'yes' === b2b_enabled ) {
|
||||
field_is_required( jQuery( '#woocommerce_eu_vat_number_field' ), true );
|
||||
}
|
||||
} else {
|
||||
jQuery( '#woocommerce_eu_vat_number_field' ).fadeOut();
|
||||
}
|
||||
});
|
||||
jQuery( '#billing_country' ).trigger( 'change' );
|
||||
|
||||
/* Validate EU VAT Number field only on change event */
|
||||
jQuery( 'form.checkout, form#order_review' ).on( 'change', '#woocommerce_eu_vat_number', function() {
|
||||
jQuery( 'body' ).trigger( 'update_checkout' );
|
||||
} );
|
||||
|
||||
/**
|
||||
* Handles checkout field UI when VAT field validation fails.
|
||||
*/
|
||||
jQuery( document.body ).on( 'updated_checkout', function( e, data ) {
|
||||
$vat_field = jQuery( '#woocommerce_eu_vat_number' );
|
||||
|
||||
if ( ! $vat_field.is( ':visible' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$vat_code = $vat_field.val();
|
||||
$vat_field_wrapper = $vat_field.closest( '.form-row' );
|
||||
|
||||
if ( 'success' === data.result ) {
|
||||
if ( ! $vat_code.length ) {
|
||||
$vat_field_wrapper.removeClass( 'woocommerce-validated' );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** If the message includes the VAT number, then highlight the VAT field in red. */
|
||||
if ( data.messages.length && data.messages.includes( $vat_code.toUpperCase() ) ) {
|
||||
$vat_field_wrapper.removeClass( 'woocommerce-validated' );
|
||||
$vat_field_wrapper.addClass( 'woocommerce-invalid' );
|
||||
}
|
||||
} )
|
||||
});
|
||||
jQuery(function(){
|
||||
function field_is_required( field, is_required ) {
|
||||
if ( is_required ) {
|
||||
field.find( 'label .optional' ).remove();
|
||||
field.addClass( 'validate-required' );
|
||||
|
||||
if ( field.find( 'label .required' ).length === 0 ) {
|
||||
field.find( 'label' ).append(
|
||||
' <abbr class="required" title="' +
|
||||
wc_address_i18n_params.i18n_required_text +
|
||||
'">*</abbr>'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
field.find( 'label .required' ).remove();
|
||||
field.removeClass( 'validate-required woocommerce-invalid woocommerce-invalid-required-field' );
|
||||
|
||||
if ( field.find( 'label .optional' ).length === 0 ) {
|
||||
field.find( 'label' ).append( ' <span class="optional">(' + wc_address_i18n_params.i18n_optional_text + ')</span>' );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
jQuery( 'form.checkout, form#order_review').on( 'change', '#billing_country', function() {
|
||||
var country = jQuery( '#billing_country' ).val();
|
||||
var check_countries = wc_eu_vat_params.eu_countries;
|
||||
var b2b_enabled = wc_eu_vat_params.b2b_required;
|
||||
|
||||
field_is_required( jQuery( '#woocommerce_eu_vat_number_field' ), false );
|
||||
|
||||
if ( country && jQuery.inArray( country, check_countries ) >= 0 ) {
|
||||
jQuery( '#woocommerce_eu_vat_number_field' ).fadeIn();
|
||||
if ( 'yes' === b2b_enabled ) {
|
||||
field_is_required( jQuery( '#woocommerce_eu_vat_number_field' ), true );
|
||||
}
|
||||
} else {
|
||||
jQuery( '#woocommerce_eu_vat_number_field' ).fadeOut();
|
||||
}
|
||||
});
|
||||
jQuery( '#billing_country' ).trigger( 'change' );
|
||||
|
||||
/* Validate EU VAT Number field only on change event */
|
||||
jQuery( 'form.checkout, form#order_review' ).on( 'change', '#woocommerce_eu_vat_number', function() {
|
||||
jQuery( 'body' ).trigger( 'update_checkout' );
|
||||
} );
|
||||
|
||||
/**
|
||||
* Handles checkout field UI when VAT field validation fails.
|
||||
*/
|
||||
jQuery( document.body ).on( 'updated_checkout', function( e, data ) {
|
||||
$vat_field = jQuery( '#woocommerce_eu_vat_number' );
|
||||
|
||||
if ( ! $vat_field.is( ':visible' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$vat_code = $vat_field.val();
|
||||
$vat_field_wrapper = $vat_field.closest( '.form-row' );
|
||||
|
||||
if ( 'success' === data.result ) {
|
||||
if ( ! $vat_code.length ) {
|
||||
$vat_field_wrapper.removeClass( 'woocommerce-validated' );
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/** If the message includes the VAT number, then highlight the VAT field in red. */
|
||||
if ( data.messages.length && data.messages.includes( $vat_code.toUpperCase() ) ) {
|
||||
$vat_field_wrapper.removeClass( 'woocommerce-validated' );
|
||||
$vat_field_wrapper.addClass( 'woocommerce-invalid' );
|
||||
}
|
||||
} )
|
||||
});
|
||||
|
|
49
block.json
49
block.json
|
@ -1,26 +1,23 @@
|
|||
{
|
||||
"apiVersion": 2,
|
||||
"name": "woocommerce/eu-vat-number",
|
||||
"version": "1.0.0",
|
||||
"title": "EU VAT Number",
|
||||
"parent": [ "woocommerce/checkout-fields-block" ],
|
||||
"category": "woocommerce",
|
||||
"icon": "cart",
|
||||
"description": "The EU VAT Number extension lets you collect and validate EU VAT numbers during checkout to identify B2B transactions verses B2C. IP Addresses can also be validated to ensure they match the billing address. EU businesses with a valid VAT number can have their VAT removed prior to payment.",
|
||||
"supports": {
|
||||
"html": false
|
||||
},
|
||||
"textdomain": "woocommerce-eu-vat-number",
|
||||
"editorScript": "file:./build/index.js",
|
||||
"editorStyle": "file:./build/index.css",
|
||||
"style": "file:./build/index.css",
|
||||
"attributes": {
|
||||
"lock": {
|
||||
"type": "object",
|
||||
"default": {
|
||||
"remove": true,
|
||||
"move": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
"apiVersion": 2,
|
||||
"name": "woocommerce/eu-vat-number",
|
||||
"version": "1.0.0",
|
||||
"title": "EU VAT Number",
|
||||
"parent": [ "woocommerce/checkout-fields-block" ],
|
||||
"category": "woocommerce",
|
||||
"icon": "cart",
|
||||
"description": "The EU VAT Number extension lets you collect and validate EU VAT numbers during checkout to identify B2B transactions verses B2C. IP Addresses can also be validated to ensure they match the billing address. EU businesses with a valid VAT number can have their VAT removed prior to payment.",
|
||||
"supports": {
|
||||
"html": false
|
||||
},
|
||||
"textdomain": "woocommerce-eu-vat-number",
|
||||
"attributes": {
|
||||
"lock": {
|
||||
"type": "object",
|
||||
"default": {
|
||||
"remove": true,
|
||||
"move": false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
<?php return array('dependencies' => array('wc-blocks-checkout', 'wc-settings', 'wp-compose', 'wp-data', 'wp-element', 'wp-i18n'), 'version' => '87d45ecf17216813b6d1215de074478a');
|
||||
<?php return array('dependencies' => array('wc-blocks-checkout', 'wc-settings', 'wp-compose', 'wp-data', 'wp-element', 'wp-i18n'), 'version' => 'ece70d3d4ce2de6be1778d017be033ee');
|
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
|||
<?php return array('dependencies' => array('wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n'), 'version' => 'c216817065c367a517a53cf1583f8d97');
|
||||
<?php return array('dependencies' => array('wp-block-editor', 'wp-blocks', 'wp-components', 'wp-element', 'wp-i18n'), 'version' => '669f781aab7fd0be57f74d2127dcf4e1');
|
File diff suppressed because one or more lines are too long
721
changelog.txt
721
changelog.txt
|
@ -1,345 +1,378 @@
|
|||
*** EU VAT Number Changelog ***
|
||||
|
||||
*** EU VAT Number Changelog ***
|
||||
|
||||
2023-09-18 - version 2.8.8
|
||||
* Add - Displays a notice warning of limited functionality if taxes are disabled.
|
||||
* Fix - Removed broken settings link from plugin page if taxes are disabled.
|
||||
|
||||
2023-08-23 - version 2.8.7
|
||||
* Dev - Bump WordPress "tested up to" version from 6.2 to 6.3.
|
||||
* Dev - Bump WooCommerce "tested up to" version 7.9.
|
||||
* Dev - Bump WooCommerce minimum supported version from 7.2 to 7.7.
|
||||
* Dev - Bump PHP minimum supported version from 7.2 to 7.3.
|
||||
* Fix - Error saving VAT numbers using block-based checkouts.
|
||||
* Fix - PHP 8.1 deprecation notice caused by FILTER_SANITIZE_STRING.
|
||||
* Security - Added nonce and permission check when dismissing tax advice notice.
|
||||
|
||||
2023-08-07 - version 2.8.6
|
||||
* Fix - VAT number validation for number with space between country code and number.
|
||||
* Dev - Added new GitHub Workflow to run Quality Insights Toolkit tests.
|
||||
* Dev - Added Playwright end-to-end tests.
|
||||
|
||||
2023-07-05 - version 2.8.5
|
||||
* Dev - Bump WooCommerce "tested up to" version 7.8.
|
||||
* Dev - Bump WooCommerce minimum supported version from 6.8 to 7.2.
|
||||
* Dev - Bump WordPress minimum supported version from 5.8 to 6.1.
|
||||
* Dev - Ensure translations are properly defined.
|
||||
* Dev - Remove deprecated class aliases for framework classes renamed in 2.4.0.
|
||||
* Dev - Resolve coding standards issues.
|
||||
* Fix - Admin can now save multiple merchant Account IDs.
|
||||
|
||||
2023-05-30 - version 2.8.4
|
||||
* Fix - Compatibility with WooCommerce Blocks checkout flow.
|
||||
* Dev – Bump WooCommerce “tested up to” version 7.6.
|
||||
* Dev – Bump WordPress minimum supported version from 5.6 to 5.8.
|
||||
* Dev – Bump WordPress “tested up to” version 6.2.
|
||||
|
||||
2023-04-03 - version 2.8.3
|
||||
* Fix - Fatal errors if SOAP extension is not installed.
|
||||
* Fix - Plugin functions are not available when dependency requirements are not met.
|
||||
|
||||
2023-03-13 - version 2.8.2
|
||||
* Fix – Ensure WC Blocks compatibility scripts are only loaded when on a page containing WC Blocks.
|
||||
* Dev – Bump PHP minimum supported version from 7.0 to 7.2.
|
||||
* Dev – Bump WooCommerce minimum supported version from 6.0 to 6.8.
|
||||
* Dev – Bump WooCommerce “tested up to” version 7.4.
|
||||
* Dev – Resolve deprecation warning in SCSS source.
|
||||
|
||||
2023-02-27 - version 2.8.1
|
||||
* Fix – UK VAT number validation issue.
|
||||
* Tweak – Bump WooCommerce tested up to 7.3.0
|
||||
|
||||
2022-12-01 - version 2.8.0
|
||||
* Add – Ability to Collect and Validate Evidence in the WooCommerce Blocks Checkout.
|
||||
* Add – Add the EU VAT Number block as a form step in the WooCommerce Blocks Checkout.
|
||||
* Add – Support for High-performance Order Storage (“HPOS”) (formerly known as Custom Order Tables, “COT”).
|
||||
* Add – Output a zero tax line item with the reason why it’s zero in both the order email and invoice.
|
||||
* Add – New filter wc_eu_vat_number_zero_tax_reason used to modify the zero tax reason text.
|
||||
* Add – Implement support for automatic translation files delivery.
|
||||
* Add – Declare support for High-performance Order Systems (“HPOS”).
|
||||
* Fix – Issue with updating VAT code from the My Account screen.
|
||||
* Fix – Errors in PHP Coding Standards.
|
||||
* Fix – Checkout VAT field validation on failure.
|
||||
* Tweak – WC tested up to 7.1.
|
||||
* Tweak – Bump minimum WP version to 5.6.
|
||||
* Tweak – Bump minimum PHP version to 7.0.
|
||||
* Tweak – Bump minimum WC version to 6.0.
|
||||
* Tweak – Simplified notices text.
|
||||
* Dev – Update node version from 8.9.3 to 16.13.0.
|
||||
* Dev – Update npm version from 5.5.1 to 8.0.0.
|
||||
|
||||
2022-11-01 - version 2.7.0
|
||||
* Add - Support for checking out with a EU vat number field using the checkout block from WooCommerce Blocks.
|
||||
|
||||
2022-09-06 - version 2.6.0
|
||||
* Add - Support for UK VAT Number validation (using UK VAT Number API).
|
||||
* Fix - VAT validation when the field is empty.
|
||||
|
||||
2022-07-25 - version 2.5.0
|
||||
* Fix – Add float Type Casting to refunded tax to prevent the “non-numeric value” warning.
|
||||
* Fix – Display product price without VAT if a valid VAT number is saved in the customer account.
|
||||
* Update – Display a more specific message for error in connect to vies server from local environments.
|
||||
|
||||
2022-06-20 - version 2.4.3
|
||||
* Tweak - Bump Tested up to
|
||||
|
||||
2022-02-22 - version 2.4.2
|
||||
* New - Add support for Subscriptions with WooCommerce Payments.
|
||||
* Fix - Removes VAT charge from the scheduled orders.
|
||||
* Fix - PHP notice when placing an order with no VAT number.
|
||||
* Fix - "Failed Validation Handling" setting not working properly for manual admin order.
|
||||
* Fix - POT file not included in release zip.
|
||||
* Fix - Apply EU VAT straight away when creating a manual order.
|
||||
|
||||
2021-08-04 - version 2.4.1
|
||||
* Fix - Rendering the VAT field when store is selling to only one country. PR#207
|
||||
* Fix - Changing the country from non-EU to EU doesn't display the VAT field. PR#207
|
||||
* Fix - Compatibility with WooCommerce One Page Checkout. PR#208
|
||||
* Fix - VAT field not displayed on WooCommerce Subscriptions switch orders. PR#208
|
||||
* Fix - VAT validation for WooCommerce Subscripitons products with a free trial. PR#208
|
||||
|
||||
2021-07-22 - version 2.4.0
|
||||
* New - [Brexit] Add Northern Ireland (XI) VAT validation and remove GB VAT validation. PR#202
|
||||
* Fix - Properly display error messages if server IP is blocked by VIES. PR#202
|
||||
* Fix - VAT Validation on orders created via WP Admin dashboard. PR#202
|
||||
* Fix - Support for checkout field editor plugins. PR#200
|
||||
* Fix - Issues with My Account -> VAT Number endpoint when My Account is set as homepage. PR#204
|
||||
|
||||
2021-04-07 - version 2.3.26
|
||||
* Update - Fixes documentation and support links.
|
||||
* Fix - Trigger VAT number validation only on change.
|
||||
* Fix - Properly handle EU VAT privacy data erasure.
|
||||
* Update - JS updated for jQuery 3 compatibility.
|
||||
* Fix - Modified VIES API request to use HTTPS
|
||||
|
||||
2020-09-30 - version 2.3.25
|
||||
* Fix - VAT Number required when B2B not enabled.
|
||||
|
||||
2020-09-30 - version 2.3.24
|
||||
* Fix - Automatically populate VAT Number at checkout if saved to user profile.
|
||||
* Fix - VAT Number showing as required for non-EU countries when switching billing country.
|
||||
* Tweak - Lower VAT Number transient expiration time from 7 days to 1 day.
|
||||
* Tweak - Improve error message when saving VAT Number on My Account if billing address is missing.
|
||||
|
||||
2020-08-19 - version 2.3.23
|
||||
* Tweak - WordPress 5.5 compatibility.
|
||||
|
||||
2020-07-14 - version 2.3.22
|
||||
* Fix - PHP error on checkout page if order total is zero.
|
||||
|
||||
2020-07-01 - version 2.3.21
|
||||
* Add - VAT number field to user/customer profile.
|
||||
* Add - VAT number of a customer when adding a new order from admin.
|
||||
* Fix - VAT not validating correctly in checkout in all acceptance types.
|
||||
* Tweak - Use EL country code for Greece when showing tax reports.
|
||||
* Tweak - Treat Isle of Man the same as UK in regards to tax exemption.
|
||||
|
||||
2020-06-10 - version 2.3.20
|
||||
* Tweak - WC 4.2 compatibility.
|
||||
|
||||
2020-04-29 - version 2.3.19
|
||||
* Tweak - Remove legacy code.
|
||||
* Tweak - WC 4.0 compatibility.
|
||||
* Fix - VAT incorrectly being removed when Recalculate button is clicked on the order.
|
||||
|
||||
2020-02-04 - version 2.3.18
|
||||
* Fix - Use proper escaping for attributes.
|
||||
|
||||
2020-01-13 - version 2.3.17
|
||||
* Tweak - WC 3.9 compatibility.
|
||||
|
||||
2019-11-05 - version 2.3.16
|
||||
* Fix - Update WC header.
|
||||
|
||||
2019-11-05 - version 2.3.15
|
||||
* Tweak - WC 3.8 compatibility.
|
||||
|
||||
2019-08-08 - version 2.3.14
|
||||
* Fix - Adding/editing VAT in admin new order or edit order not updating VAT amount.
|
||||
* Tweak - WC 3.7 compatibility.
|
||||
|
||||
2019-04-16 - version 2.3.13
|
||||
* Tweak - WC 3.6 compatibility.
|
||||
|
||||
2019-01-07 - version 2.3.12
|
||||
* Fix - Always show VAT number field if b2b is enabled.
|
||||
|
||||
2018-09-26 - version 2.3.11
|
||||
* Update - WC tested up to 3.5
|
||||
|
||||
2018-08-21 - version 2.3.10
|
||||
* Fix - Re-deployment to fix VAT numbers being removed when order is saved.
|
||||
|
||||
2018-08-21 - version 2.3.9
|
||||
* Fix - VAT numbers were removed when order is saved.
|
||||
|
||||
2018-08-02 - version 2.3.8
|
||||
* Fix - Properly handle shipping address depending on 'Ship to different address' checked or not.
|
||||
|
||||
2018-05-22 - version 2.3.7
|
||||
* Fix - PHP deprecation notice for 'parse_str'.
|
||||
* Fix - Increasing timeout for SOAP requests.
|
||||
* Fix - Show SOAP requirement notice and disable VAT lookups if needed.
|
||||
* Add - Added woocommerce_eu_vat_number_soap_parameters filter for modifying SOAP request parameters.
|
||||
* Fix - Use proper parse_str format in ajax_update_checkout_totals.
|
||||
* Update - WC tested up to 3.4
|
||||
* Update - Privacy policy notification.
|
||||
* Update - Export/erasure hooks added.
|
||||
|
||||
2018-02-05 - version 2.3.6
|
||||
* Fix - Cached VAT lookups not applying proper exemptions
|
||||
* New - Adds a filter to be able to control which countries charge VAT, via code.
|
||||
|
||||
2018-01-17 - version 2.3.5
|
||||
* Fix - Properly handle shipping address depending on 'Ship to different address' checked or not.
|
||||
* Fix - Make SOAP request to VIES directly to help prevent IPs being blocked.
|
||||
|
||||
2017-12-13 - version 2.3.4
|
||||
* Fix - WC 3.3 compatibility.
|
||||
|
||||
2017-10-09 - version 2.3.3
|
||||
* Fix - Issue where exempt check uses both shipping and billing country for matching base country.
|
||||
|
||||
2017-08-27 - version 2.3.2
|
||||
* Fix - Issue where VAT removal from cart is applied even if the country is the same as the base country.
|
||||
* Fix - Issue where VAT number from account is always used when cart page is set to checkout.
|
||||
* Fix - Fatal error that might be thrown when updating / activating.
|
||||
|
||||
2017-07-25 - version 2.3.1
|
||||
* Update - Don't show vat number field in checkout if payment is not needed.
|
||||
* Fix - When valid VAT is in account, remove VAT from cart.
|
||||
* Fix - When b2b setting is enable, apply to only EU countries.
|
||||
|
||||
2017-06-06 - version 2.3.0
|
||||
* Fix - VAT now applies to shipping country as well.
|
||||
* Fix - Validate VAT against user submitted shipping and billing instead of whats on record.
|
||||
* Fix - Undefined variable notices on reports.
|
||||
* Fix - Shipping tax amount were not showing in reports.
|
||||
* Fix - Tax by code report not showing all types of refunds.
|
||||
* Remove - Switzerland from VAT definition.
|
||||
* Add - Enable b2b setting to force VAT to be entered.
|
||||
* Add - VAT validation on My Account VAT page.
|
||||
|
||||
2017-04-13 - version 2.2.0
|
||||
* Renamed main file.
|
||||
* PHP 7.1 compatibility.
|
||||
* Stopped saving legacy VAT Number meta key - use _vat_number.
|
||||
* Tweaked display of numbers in backend.
|
||||
* Fix - error message shown when validation fails.
|
||||
* Fix - Translation wrong gettext function used.
|
||||
|
||||
2017-01-25 - version 2.1.14
|
||||
* Fix - Increase validation request timeout from 5 to 30 seconds.
|
||||
|
||||
2016-10-08 - version 2.1.13
|
||||
* Fix - Issue where My Account endpoint doesn't initially work after activation.
|
||||
* Fix - Issue where my VAT number is cleared when billing country is changed.
|
||||
|
||||
2016-06-09 - version 2.1.12
|
||||
* Tweak - Support for tabbed My Account page introduced in WooCommerce 2.6
|
||||
* Tweak - Include VAT Number in order endpoints responses within REST API
|
||||
|
||||
2016-04-13 - version 2.1.11
|
||||
* Fix issue where VAT number is not saved to user meta after checkout
|
||||
* Fix issue of missing text domain in plugin header
|
||||
* Tweak - Added filter to alter translation file location
|
||||
|
||||
2016-03-02 - version 2.1.10
|
||||
* Fix incorrect IP address to display when IP is validated. This change also
|
||||
introduces `wc_eu_vat_self_declared_ip_address` hook to filter the IP
|
||||
address.
|
||||
|
||||
2015-09-21 - version 2.1.9
|
||||
* Add VAT number field to My Account page
|
||||
* Add Switzerland to list of VAT countries
|
||||
|
||||
2015-08-06 - version 2.1.8
|
||||
* run vat_number_is_valid if the cached result was 0 or false.
|
||||
|
||||
2015-03-12 - version 2.1.7
|
||||
* Add report for non-eu VAT taxes in the same format as the EU VAT report. Useful for accounting.
|
||||
|
||||
2015-03-12 - version 2.1.6
|
||||
* Fix report ranges.
|
||||
|
||||
2015-03-12 - version 2.1.5
|
||||
* Fix textdomain
|
||||
|
||||
2015-03-08 - version 2.1.4
|
||||
* Textdomain and POT update.
|
||||
|
||||
2015-01-08 - version 2.1.3
|
||||
* Fix localisation support.
|
||||
* Tweaked what data gets saved when dealing with regular products to avoid showing IP info when not required.
|
||||
|
||||
2015-01-08 - version 2.1.2
|
||||
* Set excemption regardless of base country (maybe_set_vat_excempt method).
|
||||
|
||||
2015-01-01 - version 2.1.1
|
||||
* Updated geolocation class for CloudFlare support.
|
||||
* When dealing with digital goods, validate users who state that they are outside of the EU, if the IP address is inside the EU.
|
||||
* Fix options when saving other tax settings.
|
||||
|
||||
2014-12-30 - version 2.1.0
|
||||
* Added new geolocation class with more reliable GeoIP functionality.
|
||||
* Only collect IP when dealing with digital goods in the cart.
|
||||
* Force total refresh so checkbox is displayed.
|
||||
|
||||
2014-10-28 - version 2.0.0
|
||||
* Refactored the plugin.
|
||||
* Added additonal options for handling of orders with non-validated VAT numbers.
|
||||
* Added IP validation option for orders with digital goods (in preperation for the EU place of supply laws in January).
|
||||
* Changed the placement and look and feel of the VAT Number field to make it fit within the WC billing section.
|
||||
* Made the VAT ID append itself to formatted billing addresses automatically.
|
||||
* Added template file to control the display of the field itself.
|
||||
* Added new meta box for viewing collected information.
|
||||
* Added column in orders panel to show IP/VAT/other evidence.
|
||||
* Added reports for EC Sales and EU Vat taxes.
|
||||
* Mixed carts - force digital goods to use taxable billing address (must use tax class named 'Digital Goods')
|
||||
* Added requirement for WC 2.2.9 to support the EU VAT rates.
|
||||
|
||||
2014-09-01 - version 1.7.2
|
||||
* Handle SERVER_BUSY responses.
|
||||
* Use transient instead of wp_cache.
|
||||
|
||||
2014-09-01 - version 1.7.1
|
||||
* Base excemption on configured tax address in tax settings.
|
||||
|
||||
2014-06-10 - version 1.7.0
|
||||
* Croatia
|
||||
* Set meta data when validated, so times when the API fails can be tracked.
|
||||
|
||||
2014-04-02 - version 1.6.0
|
||||
* Use our own woo api
|
||||
|
||||
2014-02-23 - version 1.5.9
|
||||
* Option to store unvalidated numbers as-is
|
||||
|
||||
2014-02-14 - version 1.5.8
|
||||
* Only add errors when you press the checkout process button
|
||||
|
||||
2014-02-14 - version 1.5.7
|
||||
* Fix notices after success
|
||||
|
||||
2014-02-13 - version 1.5.6
|
||||
* Clear notices before adding new ones
|
||||
|
||||
2014-01-17 - version 1.5.5
|
||||
* 2.1 Compat
|
||||
|
||||
2013-08-07 - version 1.5.4
|
||||
* Pass saved strings though __()
|
||||
|
||||
2013-03-15 - version 1.5.3
|
||||
* Greece uses EL instead of GR
|
||||
|
||||
2013-03-15 - version 1.5.1
|
||||
* Update on change field
|
||||
|
||||
2013-01-11 - version 1.5.0
|
||||
* WC 2.0 Compat
|
||||
* General cleanup
|
||||
|
||||
2012-12-04 - version 1.4.1
|
||||
* New updater
|
||||
|
||||
2012-04-10 - version 1.4
|
||||
* Added option to optionally deduct tax for shop base country if a valid number is added
|
||||
|
||||
2012-04-10 - version 1.3
|
||||
* Option to show field when the customer is in the base country
|
||||
* Handling for if isvat service is down - allow vat number through.
|
||||
|
||||
2012-03-11 - version 1.2.2
|
||||
* Add inline JS for scripts
|
||||
|
||||
2012-03-01 - version 1.2.1
|
||||
* Fixed check after removing the number
|
||||
* Remove full stops from number
|
||||
|
||||
2012-01-26 - version 1.2
|
||||
* WC 1.4 Compatibility
|
||||
* Added Woo Updater
|
||||
|
||||
2011-11-15 - version 1.1.1
|
||||
* Changed textdomain
|
||||
|
||||
1.1
|
||||
* Renamed plugin since exempt is not the correct terminology
|
||||
* Show/hide VAT Number form based on country
|
||||
* If user is in the same country then don't allow zero rate
|
||||
* VAT Number added to emails
|
||||
|
||||
2011-10-26 - version 1.0.1
|
||||
* Added form-row-wide class
|
||||
* Added heading + option for title
|
||||
* Moved to shipping column, below order details
|
||||
|
||||
2011-09-27 - version 1.0
|
||||
* First Release
|
||||
* Fix - Fatal errors if SOAP extension is not installed.
|
||||
* Fix - Plugin functions are not available when dependency requirements are not met.
|
||||
|
||||
2023-03-13 - version 2.8.2
|
||||
* Fix – Ensure WC Blocks compatibility scripts are only loaded when on a page containing WC Blocks.
|
||||
* Dev – Bump PHP minimum supported version from 7.0 to 7.2.
|
||||
* Dev – Bump WooCommerce minimum supported version from 6.0 to 6.8.
|
||||
* Dev – Bump WooCommerce “tested up to” version 7.4.
|
||||
* Dev – Resolve deprecation warning in SCSS source.
|
||||
|
||||
2023-02-27 - version 2.8.1
|
||||
* Fix – UK VAT number validation issue.
|
||||
* Tweak – Bump WooCommerce tested up to 7.3.0
|
||||
|
||||
2022-12-01 - version 2.8.0
|
||||
* Add – Ability to Collect and Validate Evidence in the WooCommerce Blocks Checkout.
|
||||
* Add – Add the EU VAT Number block as a form step in the WooCommerce Blocks Checkout.
|
||||
* Add – Support for High-performance Order Storage (“HPOS”) (formerly known as Custom Order Tables, “COT”).
|
||||
* Add – Output a zero tax line item with the reason why it’s zero in both the order email and invoice.
|
||||
* Add – New filter wc_eu_vat_number_zero_tax_reason used to modify the zero tax reason text.
|
||||
* Add – Implement support for automatic translation files delivery.
|
||||
* Add – Declare support for High-performance Order Systems (“HPOS”).
|
||||
* Fix – Issue with updating VAT code from the My Account screen.
|
||||
* Fix – Errors in PHP Coding Standards.
|
||||
* Fix – Checkout VAT field validation on failure.
|
||||
* Tweak – WC tested up to 7.1.
|
||||
* Tweak – Bump minimum WP version to 5.6.
|
||||
* Tweak – Bump minimum PHP version to 7.0.
|
||||
* Tweak – Bump minimum WC version to 6.0.
|
||||
* Tweak – Simplified notices text.
|
||||
* Dev – Update node version from 8.9.3 to 16.13.0.
|
||||
* Dev – Update npm version from 5.5.1 to 8.0.0.
|
||||
|
||||
2022-11-01 - version 2.7.0
|
||||
* Add - Support for checking out with a EU vat number field using the checkout block from WooCommerce Blocks.
|
||||
|
||||
2022-09-06 - version 2.6.0
|
||||
* Add - Support for UK VAT Number validation (using UK VAT Number API).
|
||||
* Fix - VAT validation when the field is empty.
|
||||
|
||||
2022-07-25 - version 2.5.0
|
||||
* Fix – Add float Type Casting to refunded tax to prevent the “non-numeric value” warning.
|
||||
* Fix – Display product price without VAT if a valid VAT number is saved in the customer account.
|
||||
* Update – Display a more specific message for error in connect to vies server from local environments.
|
||||
|
||||
2022-06-20 - version 2.4.3
|
||||
* Tweak - Bump Tested up to
|
||||
|
||||
2022-02-22 - version 2.4.2
|
||||
* New - Add support for Subscriptions with WooCommerce Payments.
|
||||
* Fix - Removes VAT charge from the scheduled orders.
|
||||
* Fix - PHP notice when placing an order with no VAT number.
|
||||
* Fix - "Failed Validation Handling" setting not working properly for manual admin order.
|
||||
* Fix - POT file not included in release zip.
|
||||
* Fix - Apply EU VAT straight away when creating a manual order.
|
||||
|
||||
2021-08-04 - version 2.4.1
|
||||
* Fix - Rendering the VAT field when store is selling to only one country. PR#207
|
||||
* Fix - Changing the country from non-EU to EU doesn't display the VAT field. PR#207
|
||||
* Fix - Compatibility with WooCommerce One Page Checkout. PR#208
|
||||
* Fix - VAT field not displayed on WooCommerce Subscriptions switch orders. PR#208
|
||||
* Fix - VAT validation for WooCommerce Subscripitons products with a free trial. PR#208
|
||||
|
||||
2021-07-22 - version 2.4.0
|
||||
* New - [Brexit] Add Northern Ireland (XI) VAT validation and remove GB VAT validation. PR#202
|
||||
* Fix - Properly display error messages if server IP is blocked by VIES. PR#202
|
||||
* Fix - VAT Validation on orders created via WP Admin dashboard. PR#202
|
||||
* Fix - Support for checkout field editor plugins. PR#200
|
||||
* Fix - Issues with My Account -> VAT Number endpoint when My Account is set as homepage. PR#204
|
||||
|
||||
2021-04-07 - version 2.3.26
|
||||
* Update - Fixes documentation and support links.
|
||||
* Fix - Trigger VAT number validation only on change.
|
||||
* Fix - Properly handle EU VAT privacy data erasure.
|
||||
* Update - JS updated for jQuery 3 compatibility.
|
||||
* Fix - Modified VIES API request to use HTTPS
|
||||
|
||||
2020-09-30 - version 2.3.25
|
||||
* Fix - VAT Number required when B2B not enabled.
|
||||
|
||||
2020-09-30 - version 2.3.24
|
||||
* Fix - Automatically populate VAT Number at checkout if saved to user profile.
|
||||
* Fix - VAT Number showing as required for non-EU countries when switching billing country.
|
||||
* Tweak - Lower VAT Number transient expiration time from 7 days to 1 day.
|
||||
* Tweak - Improve error message when saving VAT Number on My Account if billing address is missing.
|
||||
|
||||
2020-08-19 - version 2.3.23
|
||||
* Tweak - WordPress 5.5 compatibility.
|
||||
|
||||
2020-07-14 - version 2.3.22
|
||||
* Fix - PHP error on checkout page if order total is zero.
|
||||
|
||||
2020-07-01 - version 2.3.21
|
||||
* Add - VAT number field to user/customer profile.
|
||||
* Add - VAT number of a customer when adding a new order from admin.
|
||||
* Fix - VAT not validating correctly in checkout in all acceptance types.
|
||||
* Tweak - Use EL country code for Greece when showing tax reports.
|
||||
* Tweak - Treat Isle of Man the same as UK in regards to tax exemption.
|
||||
|
||||
2020-06-10 - version 2.3.20
|
||||
* Tweak - WC 4.2 compatibility.
|
||||
|
||||
2020-04-29 - version 2.3.19
|
||||
* Tweak - Remove legacy code.
|
||||
* Tweak - WC 4.0 compatibility.
|
||||
* Fix - VAT incorrectly being removed when Recalculate button is clicked on the order.
|
||||
|
||||
2020-02-04 - version 2.3.18
|
||||
* Fix - Use proper escaping for attributes.
|
||||
|
||||
2020-01-13 - version 2.3.17
|
||||
* Tweak - WC 3.9 compatibility.
|
||||
|
||||
2019-11-05 - version 2.3.16
|
||||
* Fix - Update WC header.
|
||||
|
||||
2019-11-05 - version 2.3.15
|
||||
* Tweak - WC 3.8 compatibility.
|
||||
|
||||
2019-08-08 - version 2.3.14
|
||||
* Fix - Adding/editing VAT in admin new order or edit order not updating VAT amount.
|
||||
* Tweak - WC 3.7 compatibility.
|
||||
|
||||
2019-04-16 - version 2.3.13
|
||||
* Tweak - WC 3.6 compatibility.
|
||||
|
||||
2019-01-07 - version 2.3.12
|
||||
* Fix - Always show VAT number field if b2b is enabled.
|
||||
|
||||
2018-09-26 - version 2.3.11
|
||||
* Update - WC tested up to 3.5
|
||||
|
||||
2018-08-21 - version 2.3.10
|
||||
* Fix - Re-deployment to fix VAT numbers being removed when order is saved.
|
||||
|
||||
2018-08-21 - version 2.3.9
|
||||
* Fix - VAT numbers were removed when order is saved.
|
||||
|
||||
2018-08-02 - version 2.3.8
|
||||
* Fix - Properly handle shipping address depending on 'Ship to different address' checked or not.
|
||||
|
||||
2018-05-22 - version 2.3.7
|
||||
* Fix - PHP deprecation notice for 'parse_str'.
|
||||
* Fix - Increasing timeout for SOAP requests.
|
||||
* Fix - Show SOAP requirement notice and disable VAT lookups if needed.
|
||||
* Add - Added woocommerce_eu_vat_number_soap_parameters filter for modifying SOAP request parameters.
|
||||
* Fix - Use proper parse_str format in ajax_update_checkout_totals.
|
||||
* Update - WC tested up to 3.4
|
||||
* Update - Privacy policy notification.
|
||||
* Update - Export/erasure hooks added.
|
||||
|
||||
2018-02-05 - version 2.3.6
|
||||
* Fix - Cached VAT lookups not applying proper exemptions
|
||||
* New - Adds a filter to be able to control which countries charge VAT, via code.
|
||||
|
||||
2018-01-17 - version 2.3.5
|
||||
* Fix - Properly handle shipping address depending on 'Ship to different address' checked or not.
|
||||
* Fix - Make SOAP request to VIES directly to help prevent IPs being blocked.
|
||||
|
||||
2017-12-13 - version 2.3.4
|
||||
* Fix - WC 3.3 compatibility.
|
||||
|
||||
2017-10-09 - version 2.3.3
|
||||
* Fix - Issue where exempt check uses both shipping and billing country for matching base country.
|
||||
|
||||
2017-08-27 - version 2.3.2
|
||||
* Fix - Issue where VAT removal from cart is applied even if the country is the same as the base country.
|
||||
* Fix - Issue where VAT number from account is always used when cart page is set to checkout.
|
||||
* Fix - Fatal error that might be thrown when updating / activating.
|
||||
|
||||
2017-07-25 - version 2.3.1
|
||||
* Update - Don't show vat number field in checkout if payment is not needed.
|
||||
* Fix - When valid VAT is in account, remove VAT from cart.
|
||||
* Fix - When b2b setting is enable, apply to only EU countries.
|
||||
|
||||
2017-06-06 - version 2.3.0
|
||||
* Fix - VAT now applies to shipping country as well.
|
||||
* Fix - Validate VAT against user submitted shipping and billing instead of whats on record.
|
||||
* Fix - Undefined variable notices on reports.
|
||||
* Fix - Shipping tax amount were not showing in reports.
|
||||
* Fix - Tax by code report not showing all types of refunds.
|
||||
* Remove - Switzerland from VAT definition.
|
||||
* Add - Enable b2b setting to force VAT to be entered.
|
||||
* Add - VAT validation on My Account VAT page.
|
||||
|
||||
2017-04-13 - version 2.2.0
|
||||
* Renamed main file.
|
||||
* PHP 7.1 compatibility.
|
||||
* Stopped saving legacy VAT Number meta key - use _vat_number.
|
||||
* Tweaked display of numbers in backend.
|
||||
* Fix - error message shown when validation fails.
|
||||
* Fix - Translation wrong gettext function used.
|
||||
|
||||
2017-01-25 - version 2.1.14
|
||||
* Fix - Increase validation request timeout from 5 to 30 seconds.
|
||||
|
||||
2016-10-08 - version 2.1.13
|
||||
* Fix - Issue where My Account endpoint doesn't initially work after activation.
|
||||
* Fix - Issue where my VAT number is cleared when billing country is changed.
|
||||
|
||||
2016-06-09 - version 2.1.12
|
||||
* Tweak - Support for tabbed My Account page introduced in WooCommerce 2.6
|
||||
* Tweak - Include VAT Number in order endpoints responses within REST API
|
||||
|
||||
2016-04-13 - version 2.1.11
|
||||
* Fix issue where VAT number is not saved to user meta after checkout
|
||||
* Fix issue of missing text domain in plugin header
|
||||
* Tweak - Added filter to alter translation file location
|
||||
|
||||
2016-03-02 - version 2.1.10
|
||||
* Fix incorrect IP address to display when IP is validated. This change also
|
||||
introduces `wc_eu_vat_self_declared_ip_address` hook to filter the IP
|
||||
address.
|
||||
|
||||
2015-09-21 - version 2.1.9
|
||||
* Add VAT number field to My Account page
|
||||
* Add Switzerland to list of VAT countries
|
||||
|
||||
2015-08-06 - version 2.1.8
|
||||
* run vat_number_is_valid if the cached result was 0 or false.
|
||||
|
||||
2015-03-12 - version 2.1.7
|
||||
* Add report for non-eu VAT taxes in the same format as the EU VAT report. Useful for accounting.
|
||||
|
||||
2015-03-12 - version 2.1.6
|
||||
* Fix report ranges.
|
||||
|
||||
2015-03-12 - version 2.1.5
|
||||
* Fix textdomain
|
||||
|
||||
2015-03-08 - version 2.1.4
|
||||
* Textdomain and POT update.
|
||||
|
||||
2015-01-08 - version 2.1.3
|
||||
* Fix localisation support.
|
||||
* Tweaked what data gets saved when dealing with regular products to avoid showing IP info when not required.
|
||||
|
||||
2015-01-08 - version 2.1.2
|
||||
* Set excemption regardless of base country (maybe_set_vat_excempt method).
|
||||
|
||||
2015-01-01 - version 2.1.1
|
||||
* Updated geolocation class for CloudFlare support.
|
||||
* When dealing with digital goods, validate users who state that they are outside of the EU, if the IP address is inside the EU.
|
||||
* Fix options when saving other tax settings.
|
||||
|
||||
2014-12-30 - version 2.1.0
|
||||
* Added new geolocation class with more reliable GeoIP functionality.
|
||||
* Only collect IP when dealing with digital goods in the cart.
|
||||
* Force total refresh so checkbox is displayed.
|
||||
|
||||
2014-10-28 - version 2.0.0
|
||||
* Refactored the plugin.
|
||||
* Added additonal options for handling of orders with non-validated VAT numbers.
|
||||
* Added IP validation option for orders with digital goods (in preperation for the EU place of supply laws in January).
|
||||
* Changed the placement and look and feel of the VAT Number field to make it fit within the WC billing section.
|
||||
* Made the VAT ID append itself to formatted billing addresses automatically.
|
||||
* Added template file to control the display of the field itself.
|
||||
* Added new meta box for viewing collected information.
|
||||
* Added column in orders panel to show IP/VAT/other evidence.
|
||||
* Added reports for EC Sales and EU Vat taxes.
|
||||
* Mixed carts - force digital goods to use taxable billing address (must use tax class named 'Digital Goods')
|
||||
* Added requirement for WC 2.2.9 to support the EU VAT rates.
|
||||
|
||||
2014-09-01 - version 1.7.2
|
||||
* Handle SERVER_BUSY responses.
|
||||
* Use transient instead of wp_cache.
|
||||
|
||||
2014-09-01 - version 1.7.1
|
||||
* Base excemption on configured tax address in tax settings.
|
||||
|
||||
2014-06-10 - version 1.7.0
|
||||
* Croatia
|
||||
* Set meta data when validated, so times when the API fails can be tracked.
|
||||
|
||||
2014-04-02 - version 1.6.0
|
||||
* Use our own woo api
|
||||
|
||||
2014-02-23 - version 1.5.9
|
||||
* Option to store unvalidated numbers as-is
|
||||
|
||||
2014-02-14 - version 1.5.8
|
||||
* Only add errors when you press the checkout process button
|
||||
|
||||
2014-02-14 - version 1.5.7
|
||||
* Fix notices after success
|
||||
|
||||
2014-02-13 - version 1.5.6
|
||||
* Clear notices before adding new ones
|
||||
|
||||
2014-01-17 - version 1.5.5
|
||||
* 2.1 Compat
|
||||
|
||||
2013-08-07 - version 1.5.4
|
||||
* Pass saved strings though __()
|
||||
|
||||
2013-03-15 - version 1.5.3
|
||||
* Greece uses EL instead of GR
|
||||
|
||||
2013-03-15 - version 1.5.1
|
||||
* Update on change field
|
||||
|
||||
2013-01-11 - version 1.5.0
|
||||
* WC 2.0 Compat
|
||||
* General cleanup
|
||||
|
||||
2012-12-04 - version 1.4.1
|
||||
* New updater
|
||||
|
||||
2012-04-10 - version 1.4
|
||||
* Added option to optionally deduct tax for shop base country if a valid number is added
|
||||
|
||||
2012-04-10 - version 1.3
|
||||
* Option to show field when the customer is in the base country
|
||||
* Handling for if isvat service is down - allow vat number through.
|
||||
|
||||
2012-03-11 - version 1.2.2
|
||||
* Add inline JS for scripts
|
||||
|
||||
2012-03-01 - version 1.2.1
|
||||
* Fixed check after removing the number
|
||||
* Remove full stops from number
|
||||
|
||||
2012-01-26 - version 1.2
|
||||
* WC 1.4 Compatibility
|
||||
* Added Woo Updater
|
||||
|
||||
2011-11-15 - version 1.1.1
|
||||
* Changed textdomain
|
||||
|
||||
1.1
|
||||
* Renamed plugin since exempt is not the correct terminology
|
||||
* Show/hide VAT Number form based on country
|
||||
* If user is in the same country then don't allow zero rate
|
||||
* VAT Number added to emails
|
||||
|
||||
2011-10-26 - version 1.0.1
|
||||
* Added form-row-wide class
|
||||
* Added heading + option for title
|
||||
* Moved to shipping column, below order details
|
||||
|
||||
2011-09-27 - version 1.0
|
||||
* First Release
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
<?php
|
||||
/**
|
||||
* Backwards compatibility for old main file.
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$active_plugins = get_option( 'active_plugins', array() );
|
||||
|
||||
foreach ( $active_plugins as $key => $active_plugin ) {
|
||||
if ( strstr( $active_plugin, '/eu-vat-number.php' ) ) {
|
||||
$active_plugins[ $key ] = str_replace( '/eu-vat-number.php', '/woocommerce-eu-vat-number.php', $active_plugin );
|
||||
}
|
||||
}
|
||||
update_option( 'active_plugins', $active_plugins );
|
||||
<?php
|
||||
/**
|
||||
* Backwards compatibility for old main file.
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$active_plugins = get_option( 'active_plugins', array() );
|
||||
|
||||
foreach ( $active_plugins as $key => $active_plugin ) {
|
||||
if ( strstr( $active_plugin, '/eu-vat-number.php' ) ) {
|
||||
$active_plugins[ $key ] = str_replace( '/eu-vat-number.php', '/woocommerce-eu-vat-number.php', $active_plugin );
|
||||
}
|
||||
}
|
||||
update_option( 'active_plugins', $active_plugins );
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,331 +1,332 @@
|
|||
<?php
|
||||
/**
|
||||
* Blocks handling.
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
*/
|
||||
|
||||
use Automattic\WooCommerce\Blocks\Integrations\IntegrationInterface;
|
||||
use Automattic\WooCommerce\StoreApi\Schemas\V1\CheckoutSchema;
|
||||
use Automattic\WooCommerce\StoreApi\Schemas\V1\CartSchema;
|
||||
use Automattic\WooCommerce\StoreApi\StoreApi;
|
||||
use Automattic\WooCommerce\StoreApi\Schemas\ExtendSchema;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_EU_VAT_Blocks class.
|
||||
*/
|
||||
class WC_EU_VAT_Blocks_Integration implements IntegrationInterface {
|
||||
|
||||
/**
|
||||
* The name of the integration.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_name() {
|
||||
return 'woocommerce-eu-vat-number';
|
||||
}
|
||||
|
||||
/**
|
||||
* When called invokes any initialization/setup for the integration.
|
||||
*/
|
||||
public function initialize() {
|
||||
$asset_file_front = include plugin_dir_path( __FILE__ ) . '../build/frontend.asset.php';
|
||||
wp_register_script(
|
||||
'wc-blocks-eu-vat-scripts-frontend',
|
||||
plugins_url( 'build/frontend.js', __DIR__ ),
|
||||
$asset_file_front['dependencies'],
|
||||
$asset_file_front['version'],
|
||||
true
|
||||
);
|
||||
|
||||
add_action( 'woocommerce_store_api_checkout_update_order_meta', array( $this, 'update_order_meta' ), 10, 1 );
|
||||
add_action( 'woocommerce_store_api_checkout_update_order_from_request', array( $this, 'update_order_from_request' ), 10, 2 );
|
||||
$this->extend_rest_api();
|
||||
}
|
||||
|
||||
/**
|
||||
* When an order is completed, woocommerce_store_api_checkout_update_order_from_request is fired. This action allows
|
||||
* extensions to update the customer's order. In this method, we set the customer's self-delared country and the
|
||||
* country we think they are from based on their IP.
|
||||
*
|
||||
* @param WC_Order $order The current customer's order object.
|
||||
* @param WP_REST_Request $request The API request currently being processed.
|
||||
* @return void
|
||||
*/
|
||||
public function update_order_from_request( $order, $request ) {
|
||||
if ( false !== WC_EU_VAT_Number::get_ip_country() ) {
|
||||
$order->update_meta_data( '_customer_ip_country', WC_EU_VAT_Number::get_ip_country() );
|
||||
$order->update_meta_data( '_customer_self_declared_country', ! empty( $request['extensions']['woocommerce-eu-vat-number']['location_confirmation'] ) ? 'true' : 'false' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of script handles to enqueue in the frontend context.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function get_script_handles() {
|
||||
return array( 'wc-blocks-eu-vat-scripts-frontend' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of script handles to enqueue in the editor context.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function get_editor_script_handles() {
|
||||
return array( 'wc-blocks-eu-vat-scripts-frontend' );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An array of key, value pairs of data made available to the block on the client side.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_script_data() {
|
||||
return array(
|
||||
'ip_country' => WC_EU_VAT_Number::get_ip_country(),
|
||||
'ip_address' => apply_filters( 'wc_eu_vat_self_declared_ip_address', WC_Geolocation::get_ip_address() ),
|
||||
'woocommerce_eu_vat_number_validate_ip' => get_option( 'woocommerce_eu_vat_number_validate_ip', 'no' ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores Rest Extending instance.
|
||||
*
|
||||
* @var ExtendRestApi
|
||||
*/
|
||||
private static $extend;
|
||||
|
||||
/**
|
||||
* Adding order meta data that are part of the plugin of orders created using the
|
||||
* checkout block.
|
||||
*
|
||||
* @param WC_Order $order The order being placed.
|
||||
* @return void
|
||||
*/
|
||||
public function update_order_meta( $order ) {
|
||||
|
||||
if ( ! $order instanceof \WC_Order ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$vat_number = WC()->session->get( 'vat-number' );
|
||||
if ( ! $vat_number ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$data = $this::validate();
|
||||
$order->update_meta_data( '_vat_number_is_validated', ! is_null( $data['validation']['valid'] ) ? 'true' : 'false' );
|
||||
$order->update_meta_data( '_vat_number_is_valid', true === $data['validation']['valid'] ? 'true' : 'false' );
|
||||
$order->update_meta_data( '_billing_vat_number', $vat_number );
|
||||
|
||||
if ( false !== WC_EU_VAT_Number::get_ip_country() ) {
|
||||
$order->update_meta_data( '_customer_ip_country', WC_EU_VAT_Number::get_ip_country() );
|
||||
}
|
||||
|
||||
$this->maybe_apply_exemption();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers extensions to two rest API endpoints:
|
||||
* 1 - a cart update endpoint to get the VAT number after it has been typed and check for
|
||||
* vat excepmption while on the checkout form.
|
||||
* 2 - a checkout endpoint extension to inform our frontend component about the result of
|
||||
* the validity of the VAT number and react accordingly.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function extend_rest_api() {
|
||||
|
||||
/**
|
||||
* A cart update endpoint to get the VAT number after it has been typed and check for
|
||||
* vat exemption while on the checkout form.
|
||||
*/
|
||||
$extend = StoreApi::container()->get( ExtendSchema::class );
|
||||
|
||||
$extend->register_update_callback(
|
||||
array(
|
||||
'namespace' => 'woocommerce-eu-vat-number',
|
||||
'callback' => function( $data ) {
|
||||
if ( isset( $data['vat_number'] ) ) {
|
||||
if ( empty( $data['vat_number'] ) ) {
|
||||
WC()->session->set( 'vat-number', null );
|
||||
WC()->customer->set_is_vat_exempt( false );
|
||||
} else {
|
||||
WC()->session->set( 'vat-number', strtoupper( $data['vat_number'] ) );
|
||||
$this->maybe_apply_exemption( false );
|
||||
}
|
||||
} else {
|
||||
WC()->session->set( 'vat-number', null );
|
||||
WC()->customer->set_is_vat_exempt( false );
|
||||
}
|
||||
},
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* A checkout endpoint extension to inform our frontend component about the result of
|
||||
* the validity of the VAT number and react accordingly.
|
||||
*/
|
||||
$extend->register_endpoint_data(
|
||||
array(
|
||||
'endpoint' => CartSchema::IDENTIFIER,
|
||||
'namespace' => 'woocommerce-eu-vat-number',
|
||||
'data_callback' => array( $this, 'vat_number_information' ),
|
||||
'schema_callback' => array( $this, 'schema_for_vat_number_information' ),
|
||||
'schema_type' => ARRAY_A,
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* A checkout endpoint to accept the location_confirmation key.
|
||||
*/
|
||||
$extend->register_endpoint_data(
|
||||
array(
|
||||
'endpoint' => CheckoutSchema::IDENTIFIER,
|
||||
'namespace' => 'woocommerce-eu-vat-number',
|
||||
'schema_callback' => function() {
|
||||
return array(
|
||||
'location_confirmation' => array(
|
||||
'description' => __( 'Location confirmation.', 'woocommerce-eu-vat-number' ),
|
||||
'type' => 'boolean',
|
||||
'context' => array(),
|
||||
),
|
||||
);
|
||||
},
|
||||
'schema_type' => ARRAY_A,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about the status of the given VAT Number.
|
||||
*
|
||||
* @return Array Information about the validity of the VAT Number.
|
||||
*/
|
||||
public function vat_number_information() {
|
||||
return array_merge( $this::validate(), array( 'cart_has_digital_goods' => WC_EU_VAT_Number::cart_has_digital_goods() ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if VAT number is formatted correctly.
|
||||
*
|
||||
* @return Array Information about the result of the validation.
|
||||
*/
|
||||
public function validate() {
|
||||
$data = array();
|
||||
$vat_number = WC()->session->get( 'vat-number' );
|
||||
$country = WC()->customer->get_billing_country();
|
||||
$postcode = WC()->customer->get_billing_postcode();
|
||||
$fail_handler = get_option( 'woocommerce_eu_vat_number_failure_handling', 'reject' );
|
||||
$valid = WC_EU_VAT_Number::vat_number_is_valid( $vat_number, $country, $postcode );
|
||||
|
||||
if ( is_wp_error( $valid ) ) {
|
||||
$data['vat_number'] = $vat_number;
|
||||
$data['validation'] = array(
|
||||
'valid' => false,
|
||||
'error' => $valid->get_error_message(),
|
||||
);
|
||||
return $data;
|
||||
}
|
||||
|
||||
$vat_number_formatted = WC_EU_VAT_Number::get_formatted_vat_number( $vat_number );
|
||||
$data['vat_number'] = $valid ? WC_EU_VAT_Number::get_vat_number_prefix( $country ) . $vat_number_formatted : $vat_number;
|
||||
$data['validation'] = array(
|
||||
'valid' => $valid,
|
||||
'error' => false,
|
||||
);
|
||||
|
||||
if ( 'reject' === $fail_handler && ( ! $valid || ! $vat_number ) ) {
|
||||
$data['validation']['error'] = ! $valid ? __( 'Invalid VAT number.', 'woocommerce-eu-vat-number' ) : false;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates VAT Number and tries to apply the exemption given the information.
|
||||
*
|
||||
* @param boolean $with_notices Indicates whether to add notices or just run without any feedback.
|
||||
* This is used while chaning the field on the checkout for and when submitting the order, hence
|
||||
* the two separate use cases.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function maybe_apply_exemption( $with_notices = true ) {
|
||||
|
||||
$vat_number = WC()->session->get( 'vat-number' );
|
||||
|
||||
if ( ! $vat_number ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$validation = $this::validate();
|
||||
$fail_handler = get_option( 'woocommerce_eu_vat_number_failure_handling', 'reject' );
|
||||
|
||||
if ( false === (bool) $validation['validation']['valid'] && $with_notices ) {
|
||||
switch ( $fail_handler ) {
|
||||
case 'accept_with_vat':
|
||||
wc_add_notice( $validation['validation']['error'], 'error' );
|
||||
break;
|
||||
case 'accept':
|
||||
break;
|
||||
default:
|
||||
wc_add_notice( $validation['validation']['error'], 'error' );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->set_vat_exemption( $validation );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to apply the exemption given the information.
|
||||
*
|
||||
* @param mixed $validation Result of the validation of the VAT Number.
|
||||
* @return void
|
||||
*/
|
||||
private function set_vat_exemption( $validation ) {
|
||||
|
||||
$fail_handler = get_option( 'woocommerce_eu_vat_number_failure_handling', 'reject' );
|
||||
$b_country = WC()->customer->get_billing_country();
|
||||
$s_country = WC()->customer->get_shipping_country();
|
||||
|
||||
if ( true === (bool) $validation['validation']['valid'] ) {
|
||||
WC_EU_VAT_Number::maybe_set_vat_exempt( true, $b_country, $s_country );
|
||||
} else {
|
||||
switch ( $fail_handler ) {
|
||||
case 'accept_with_vat':
|
||||
WC_EU_VAT_Number::maybe_set_vat_exempt( false, $b_country, $s_country );
|
||||
break;
|
||||
case 'accept':
|
||||
WC_EU_VAT_Number::maybe_set_vat_exempt( true, $b_country, $s_country );
|
||||
break;
|
||||
default:
|
||||
WC_EU_VAT_Number::maybe_set_vat_exempt( false, $b_country, $s_country );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Schema for the information about the VAT Number.
|
||||
*
|
||||
* @return Array Information about this vat number.
|
||||
*/
|
||||
public function schema_for_vat_number_information() {
|
||||
return array(
|
||||
'vat_data' => array(
|
||||
'description' => __( 'VAT Data', 'woocommerce-eu-vat-number' ),
|
||||
'type' => 'array',
|
||||
'readonly' => true,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
<?php
|
||||
/**
|
||||
* Blocks handling.
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
*/
|
||||
|
||||
use Automattic\WooCommerce\Blocks\Integrations\IntegrationInterface;
|
||||
use Automattic\WooCommerce\StoreApi\Schemas\V1\CheckoutSchema;
|
||||
use Automattic\WooCommerce\StoreApi\Schemas\V1\CartSchema;
|
||||
use Automattic\WooCommerce\StoreApi\StoreApi;
|
||||
use Automattic\WooCommerce\StoreApi\Schemas\ExtendSchema;
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_EU_VAT_Blocks class.
|
||||
*/
|
||||
class WC_EU_VAT_Blocks_Integration implements IntegrationInterface {
|
||||
|
||||
/**
|
||||
* The name of the integration.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_name() {
|
||||
return 'woocommerce-eu-vat-number';
|
||||
}
|
||||
|
||||
/**
|
||||
* When called invokes any initialization/setup for the integration.
|
||||
*/
|
||||
public function initialize() {
|
||||
WC_EU_VAT_Number::register_script_with_dependencies( 'wc-blocks-eu-vat-scripts-frontend', 'build/frontend' );
|
||||
WC_EU_VAT_Number::register_script_with_dependencies( 'wc-blocks-eu-vat-scripts-index', 'build/index' );
|
||||
|
||||
add_action( 'woocommerce_store_api_checkout_update_order_meta', array( $this, 'update_order_meta' ), 10, 1 );
|
||||
add_action( 'woocommerce_store_api_checkout_update_order_from_request', array( $this, 'update_order_from_request' ), 10, 2 );
|
||||
$this->extend_rest_api();
|
||||
}
|
||||
|
||||
/**
|
||||
* When an order is completed, woocommerce_store_api_checkout_update_order_from_request is fired. This action allows
|
||||
* extensions to update the customer's order. In this method, we set the customer's self-delared country and the
|
||||
* country we think they are from based on their IP.
|
||||
*
|
||||
* @param WC_Order $order The current customer's order object.
|
||||
* @param WP_REST_Request $request The API request currently being processed.
|
||||
* @return void
|
||||
*/
|
||||
public function update_order_from_request( $order, $request ) {
|
||||
if ( false !== WC_EU_VAT_Number::get_ip_country() ) {
|
||||
$order->update_meta_data( '_customer_ip_country', WC_EU_VAT_Number::get_ip_country() );
|
||||
$order->update_meta_data( '_customer_self_declared_country', ! empty( $request['extensions']['woocommerce-eu-vat-number']['location_confirmation'] ) ? 'true' : 'false' );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of script handles to enqueue in the frontend context.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function get_script_handles() {
|
||||
return array( 'wc-blocks-eu-vat-scripts-frontend' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of script handles to enqueue in the editor context.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function get_editor_script_handles() {
|
||||
return array( 'wc-blocks-eu-vat-scripts-frontend', 'wc-blocks-eu-vat-scripts-index' );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* An array of key, value pairs of data made available to the block on the client side.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_script_data() {
|
||||
return array(
|
||||
'ip_country' => WC_EU_VAT_Number::get_ip_country(),
|
||||
'ip_address' => apply_filters( 'wc_eu_vat_self_declared_ip_address', WC_Geolocation::get_ip_address() ),
|
||||
'woocommerce_eu_vat_number_validate_ip' => get_option( 'woocommerce_eu_vat_number_validate_ip', 'no' ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores Rest Extending instance.
|
||||
*
|
||||
* @var ExtendRestApi
|
||||
*/
|
||||
private static $extend;
|
||||
|
||||
/**
|
||||
* Adding order meta data that are part of the plugin of orders created using the
|
||||
* checkout block.
|
||||
*
|
||||
* @param WC_Order $order The order being placed.
|
||||
* @return void
|
||||
*/
|
||||
public function update_order_meta( $order ) {
|
||||
|
||||
if ( ! $order instanceof \WC_Order ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$vat_number = WC()->session->get( 'vat-number' );
|
||||
if ( ! $vat_number ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$data = $this::validate();
|
||||
$order->update_meta_data( '_vat_number_is_validated', ! is_null( $data['validation']['valid'] ) ? 'true' : 'false' );
|
||||
$order->update_meta_data( '_vat_number_is_valid', true === $data['validation']['valid'] ? 'true' : 'false' );
|
||||
$order->update_meta_data( '_billing_vat_number', $vat_number );
|
||||
$customer_id = $order->get_customer_id();
|
||||
|
||||
if ( $customer_id ) {
|
||||
$customer = new \WC_Customer( $customer_id );
|
||||
$customer->update_meta_data( 'vat_number', $vat_number );
|
||||
$customer->save_meta_data();
|
||||
}
|
||||
|
||||
if ( false !== WC_EU_VAT_Number::get_ip_country() ) {
|
||||
$order->update_meta_data( '_customer_ip_country', WC_EU_VAT_Number::get_ip_country() );
|
||||
}
|
||||
|
||||
$this->maybe_apply_exemption();
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers extensions to two rest API endpoints:
|
||||
* 1 - a cart update endpoint to get the VAT number after it has been typed and check for
|
||||
* vat excepmption while on the checkout form.
|
||||
* 2 - a checkout endpoint extension to inform our frontend component about the result of
|
||||
* the validity of the VAT number and react accordingly.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function extend_rest_api() {
|
||||
|
||||
/**
|
||||
* A cart update endpoint to get the VAT number after it has been typed and check for
|
||||
* vat exemption while on the checkout form.
|
||||
*/
|
||||
$extend = StoreApi::container()->get( ExtendSchema::class );
|
||||
|
||||
$extend->register_update_callback(
|
||||
array(
|
||||
'namespace' => 'woocommerce-eu-vat-number',
|
||||
'callback' => function( $data ) {
|
||||
if ( isset( $data['vat_number'] ) ) {
|
||||
if ( empty( $data['vat_number'] ) ) {
|
||||
WC()->session->set( 'vat-number', null );
|
||||
WC()->customer->set_is_vat_exempt( false );
|
||||
} else {
|
||||
WC()->session->set( 'vat-number', strtoupper( $data['vat_number'] ) );
|
||||
$this->maybe_apply_exemption( false );
|
||||
}
|
||||
} else {
|
||||
WC()->session->set( 'vat-number', null );
|
||||
WC()->customer->set_is_vat_exempt( false );
|
||||
}
|
||||
},
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* A checkout endpoint extension to inform our frontend component about the result of
|
||||
* the validity of the VAT number and react accordingly.
|
||||
*/
|
||||
$extend->register_endpoint_data(
|
||||
array(
|
||||
'endpoint' => CartSchema::IDENTIFIER,
|
||||
'namespace' => 'woocommerce-eu-vat-number',
|
||||
'data_callback' => array( $this, 'vat_number_information' ),
|
||||
'schema_callback' => array( $this, 'schema_for_vat_number_information' ),
|
||||
'schema_type' => ARRAY_A,
|
||||
)
|
||||
);
|
||||
|
||||
/**
|
||||
* A checkout endpoint to accept the location_confirmation key.
|
||||
*/
|
||||
$extend->register_endpoint_data(
|
||||
array(
|
||||
'endpoint' => CheckoutSchema::IDENTIFIER,
|
||||
'namespace' => 'woocommerce-eu-vat-number',
|
||||
'schema_callback' => function() {
|
||||
return array(
|
||||
'location_confirmation' => array(
|
||||
'description' => __( 'Location confirmation.', 'woocommerce-eu-vat-number' ),
|
||||
'type' => 'boolean',
|
||||
'context' => array(),
|
||||
),
|
||||
);
|
||||
},
|
||||
'schema_type' => ARRAY_A,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about the status of the given VAT Number.
|
||||
*
|
||||
* @return Array Information about the validity of the VAT Number.
|
||||
*/
|
||||
public function vat_number_information() {
|
||||
return array_merge( $this::validate(), array( 'cart_has_digital_goods' => WC_EU_VAT_Number::cart_has_digital_goods() ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if VAT number is formatted correctly.
|
||||
*
|
||||
* @return Array Information about the result of the validation.
|
||||
*/
|
||||
public function validate() {
|
||||
$data = array();
|
||||
$vat_number = WC()->session->get( 'vat-number' );
|
||||
$country = WC()->customer->get_billing_country();
|
||||
$postcode = WC()->customer->get_billing_postcode();
|
||||
$fail_handler = get_option( 'woocommerce_eu_vat_number_failure_handling', 'reject' );
|
||||
$valid = WC_EU_VAT_Number::vat_number_is_valid( $vat_number, $country, $postcode );
|
||||
|
||||
if ( is_wp_error( $valid ) ) {
|
||||
$data['vat_number'] = $vat_number;
|
||||
$data['validation'] = array(
|
||||
'valid' => false,
|
||||
'error' => $valid->get_error_message(),
|
||||
);
|
||||
return $data;
|
||||
}
|
||||
|
||||
$vat_number_formatted = WC_EU_VAT_Number::get_formatted_vat_number( $vat_number );
|
||||
$data['vat_number'] = $valid ? WC_EU_VAT_Number::get_vat_number_prefix( $country ) . $vat_number_formatted : $vat_number;
|
||||
$data['validation'] = array(
|
||||
'valid' => $valid,
|
||||
'error' => false,
|
||||
);
|
||||
|
||||
if ( 'reject' === $fail_handler && ( ! $valid || ! $vat_number ) ) {
|
||||
$data['validation']['error'] = ! $valid ? __( 'Invalid VAT number.', 'woocommerce-eu-vat-number' ) : false;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates VAT Number and tries to apply the exemption given the information.
|
||||
*
|
||||
* @param boolean $with_notices Indicates whether to add notices or just run without any feedback.
|
||||
* This is used while chaning the field on the checkout for and when submitting the order, hence
|
||||
* the two separate use cases.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function maybe_apply_exemption( $with_notices = true ) {
|
||||
|
||||
$vat_number = WC()->session->get( 'vat-number' );
|
||||
|
||||
if ( ! $vat_number ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$validation = $this::validate();
|
||||
$fail_handler = get_option( 'woocommerce_eu_vat_number_failure_handling', 'reject' );
|
||||
|
||||
if ( false === (bool) $validation['validation']['valid'] && $with_notices ) {
|
||||
switch ( $fail_handler ) {
|
||||
case 'accept_with_vat':
|
||||
wc_add_notice( $validation['validation']['error'], 'error' );
|
||||
break;
|
||||
case 'accept':
|
||||
break;
|
||||
default:
|
||||
wc_add_notice( $validation['validation']['error'], 'error' );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->set_vat_exemption( $validation );
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to apply the exemption given the information.
|
||||
*
|
||||
* @param mixed $validation Result of the validation of the VAT Number.
|
||||
* @return void
|
||||
*/
|
||||
private function set_vat_exemption( $validation ) {
|
||||
|
||||
$fail_handler = get_option( 'woocommerce_eu_vat_number_failure_handling', 'reject' );
|
||||
$b_country = WC()->customer->get_billing_country();
|
||||
$s_country = WC()->customer->get_shipping_country();
|
||||
|
||||
if ( true === (bool) $validation['validation']['valid'] ) {
|
||||
WC_EU_VAT_Number::maybe_set_vat_exempt( true, $b_country, $s_country );
|
||||
} else {
|
||||
switch ( $fail_handler ) {
|
||||
case 'accept_with_vat':
|
||||
WC_EU_VAT_Number::maybe_set_vat_exempt( false, $b_country, $s_country );
|
||||
break;
|
||||
case 'accept':
|
||||
WC_EU_VAT_Number::maybe_set_vat_exempt( true, $b_country, $s_country );
|
||||
break;
|
||||
default:
|
||||
WC_EU_VAT_Number::maybe_set_vat_exempt( false, $b_country, $s_country );
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Schema for the information about the VAT Number.
|
||||
*
|
||||
* @return Array Information about this vat number.
|
||||
*/
|
||||
public function schema_for_vat_number_information() {
|
||||
return array(
|
||||
'vat_data' => array(
|
||||
'description' => __( 'VAT Data', 'woocommerce-eu-vat-number' ),
|
||||
'type' => 'array',
|
||||
'readonly' => true,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,261 +1,261 @@
|
|||
<?php
|
||||
/**
|
||||
* My Account Handling.
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_EU_VAT_Reports class
|
||||
*/
|
||||
class WC_EU_VAT_My_Account {
|
||||
|
||||
/**
|
||||
* URL endpoint.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $endpoint = 'vat-number';
|
||||
|
||||
/**
|
||||
* Success Messages.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $messages = array();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct() {
|
||||
|
||||
// New endpoint for vat-number WC >= 2.6.
|
||||
add_action( 'init', array( $this, 'add_endpoints' ) );
|
||||
add_filter( 'woocommerce_get_query_vars', array( $this, 'add_query_vars' ), 0 );
|
||||
|
||||
// Change My Account page title.
|
||||
add_filter( 'the_title', array( $this, 'endpoint_title' ) );
|
||||
|
||||
// Inserting new tab/page into My Account page.
|
||||
add_filter( 'woocommerce_account_menu_items', array( $this, 'new_menu_items' ) );
|
||||
add_action( 'woocommerce_account_' . $this->endpoint . '_endpoint', array( $this, 'endpoint_content' ) );
|
||||
|
||||
// Save a VAT number from My Account form if one is submitted.
|
||||
if ( isset( $_POST['action'] ) && 'edit_vat_number' === wc_clean( wp_unslash( $_POST['action'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verifying nonce inside function.
|
||||
$this->save_vat_number();
|
||||
}
|
||||
|
||||
add_action( 'woocommerce_init', array( $this, 'maybe_remove_vat' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if we need to remove vat from displaying in the cart and from product itself.
|
||||
*
|
||||
* @see https://github.com/woocommerce/woocommerce-eu-vat-number/issues/71
|
||||
* @see https://github.com/woocommerce/woocommerce-eu-vat-number/issues/74
|
||||
* @see https://github.com/woocommerce/woocommerce-eu-vat-number/issues/233
|
||||
*/
|
||||
public function maybe_remove_vat() {
|
||||
// Ignore checkout page as on checkout page VAT exempt based on VAT number from billing fields.
|
||||
if ( ( is_admin() && ! defined( 'DOING_AJAX' ) ) || ! wc_tax_enabled() || is_checkout() || ! is_user_logged_in() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$vat_number = get_user_meta( get_current_user_id(), 'vat_number', true );
|
||||
if ( empty( $vat_number ) || empty( WC()->customer ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate if VAT is valid. If valid, check for VAT exempt.
|
||||
try {
|
||||
$billing_country = WC()->customer->get_billing_country();
|
||||
$shipping_country = WC()->customer->get_shipping_country();
|
||||
|
||||
if ( $this->validate( $vat_number, $billing_country ) ) {
|
||||
WC_EU_VAT_Number::maybe_set_vat_exempt( true, $billing_country, $shipping_country );
|
||||
}
|
||||
} catch ( Exception $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
|
||||
// Ignore Exception.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new endpoint to use inside My Account page.
|
||||
*
|
||||
* @since 2.1.12
|
||||
*
|
||||
* @see https://developer.wordpress.org/reference/functions/add_rewrite_endpoint/
|
||||
*/
|
||||
public function add_endpoints() {
|
||||
add_rewrite_endpoint( $this->endpoint, EP_ROOT | EP_PAGES );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new query var.
|
||||
*
|
||||
* @since 2.1.12
|
||||
*
|
||||
* @param array $vars Query vars.
|
||||
* @return array
|
||||
*/
|
||||
public function add_query_vars( $vars ) {
|
||||
$vars[] = $this->endpoint;
|
||||
|
||||
return $vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set endpoint title.
|
||||
*
|
||||
* @since 2.1.12
|
||||
*
|
||||
* @param string $title Endpoint title.
|
||||
* @return string
|
||||
*/
|
||||
public function endpoint_title( $title ) {
|
||||
global $wp_query;
|
||||
|
||||
$is_endpoint = isset( $wp_query->query_vars[ $this->endpoint ] );
|
||||
|
||||
if ( $is_endpoint && ! is_admin() && is_main_query() && in_the_loop() && is_account_page() ) {
|
||||
$title = get_option( 'woocommerce_eu_vat_number_field_label', __( 'VAT number', 'woocommerce-eu-vat-number' ) );
|
||||
|
||||
remove_filter( 'the_title', array( $this, 'endpoint_title' ) );
|
||||
}
|
||||
|
||||
return $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert new endpoint into My Account menu.
|
||||
*
|
||||
* @since 2.1.12
|
||||
*
|
||||
* @param array $items Menu items.
|
||||
* @return array Menu items.
|
||||
*/
|
||||
public function new_menu_items( $items ) {
|
||||
// Remove logout menu item.
|
||||
$logout = $items['customer-logout'];
|
||||
unset( $items['customer-logout'] );
|
||||
|
||||
// Insert VAT Number.
|
||||
$items[ $this->endpoint ] = get_option( 'woocommerce_eu_vat_number_field_label', __( 'VAT number', 'woocommerce-eu-vat-number' ) );
|
||||
|
||||
// Insert back logout item.
|
||||
$items['customer-logout'] = $logout;
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Endpoint HTML content.
|
||||
*
|
||||
* @since 2.1.12
|
||||
*/
|
||||
public function endpoint_content() {
|
||||
$this->render_my_vat_number_content();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render My VAT Number content.
|
||||
*
|
||||
* @since 2.1.12
|
||||
*/
|
||||
public function render_my_vat_number_content() {
|
||||
$vars = array(
|
||||
'vat_number' => get_user_meta( get_current_user_id(), 'vat_number', true ),
|
||||
'messages' => $this->messages,
|
||||
);
|
||||
|
||||
wc_get_template(
|
||||
'my-account/my-vat-number.php',
|
||||
$vars,
|
||||
'woocommerce-eu-vat-number',
|
||||
untrailingslashit( plugin_dir_path( WC_EU_VAT_FILE ) ) . '/templates/'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a VAT number.
|
||||
*
|
||||
* @version 2.3.0
|
||||
* @since 2.3.0
|
||||
* @param string $vat_number VAT number passed by the form.
|
||||
* @param string $billing_country Billing country of the order.
|
||||
* @param string $billing_postcode Billing postcode of the order.
|
||||
* @param string $current_vat VAT number saved in database.
|
||||
*
|
||||
* @return boolean
|
||||
* @throws Exception For invalid VAT Number.
|
||||
*/
|
||||
public function validate( $vat_number, $billing_country, $billing_postcode = '', $current_vat = '' ) {
|
||||
if ( empty( $vat_number ) ) {
|
||||
if ( empty( $current_vat ) ) {
|
||||
throw new Exception( __( 'VAT number cannot be empty.', 'woocommerce-eu-vat-number' ) );
|
||||
}
|
||||
// Allow empty input to clear VAT field.
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( empty( $billing_country ) ) {
|
||||
/* translators: 1: VAT Number */
|
||||
throw new Exception( sprintf( __( '%1$s can not be validated because the billing country is missing. Please update your billing address.', 'woocommerce-eu-vat-number' ), '<strong>' . get_option( 'woocommerce_eu_vat_number_field_label', __( 'VAT number', 'woocommerce-eu-vat-number' ) ) . '</strong>' ) );
|
||||
}
|
||||
|
||||
$valid = WC_EU_VAT_Number::vat_number_is_valid( $vat_number, $billing_country, $billing_postcode );
|
||||
|
||||
if ( is_wp_error( $valid ) ) {
|
||||
throw new Exception( $valid->get_error_message() );
|
||||
}
|
||||
|
||||
if ( ! $valid ) {
|
||||
// translators: %1$s VAT number field label, %2$s VAT number, %3$s Billing Country.
|
||||
throw new Exception( sprintf( __( 'You have entered an invalid %1$s (%2$s) for your billing country (%3$s).', 'woocommerce-eu-vat-number' ), get_option( 'woocommerce_eu_vat_number_field_label', __( 'VAT number', 'woocommerce-eu-vat-number' ) ), $vat_number, $billing_country ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to save VAT number from the my account form.
|
||||
*/
|
||||
public function save_vat_number() {
|
||||
if ( isset( $_POST['_wpnonce'] ) && wp_verify_nonce( wp_unslash( $_POST['_wpnonce'] ), 'woocommerce-edit_vat_number' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
try {
|
||||
$current_user_id = get_current_user_id();
|
||||
$vat_number = isset( $_POST['vat_number'] ) ? wc_clean( wp_unslash( $_POST['vat_number'] ) ) : '';
|
||||
$posted_vat = strtoupper( str_replace( array( ' ', '.', '-', ',', ', ' ), '', $vat_number ) );
|
||||
$user = get_userdata( $current_user_id );
|
||||
$current_vat = $user->vat_number;
|
||||
$billing_country = $user->billing_country;
|
||||
$billing_postcode = $user->billing_postcode;
|
||||
|
||||
$this->validate( $posted_vat, $billing_country, $billing_postcode, $current_vat );
|
||||
|
||||
update_user_meta( $current_user_id, 'vat_number', $posted_vat );
|
||||
update_user_meta( $current_user_id, 'billing_vat_number', $posted_vat );
|
||||
|
||||
if ( empty( $posted_vat ) ) {
|
||||
$message = __( 'VAT number removed successfully!', 'woocommerce-eu-vat-number' );
|
||||
} elseif ( empty( $current_vat ) ) {
|
||||
$message = __( 'VAT number saved successfully!', 'woocommerce-eu-vat-number' );
|
||||
} else {
|
||||
$message = __( 'VAT number updated successfully!', 'woocommerce-eu-vat-number' );
|
||||
}
|
||||
$this->messages = array( 'message' => $message, 'status' => 'info' );
|
||||
} catch ( Exception $e ) {
|
||||
$this->messages = array(
|
||||
'message' => $e->getMessage(),
|
||||
'status' => 'error',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$wc_eu_vat_my_account = new WC_EU_VAT_My_Account();
|
||||
<?php
|
||||
/**
|
||||
* My Account Handling.
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_EU_VAT_Reports class
|
||||
*/
|
||||
class WC_EU_VAT_My_Account {
|
||||
|
||||
/**
|
||||
* URL endpoint.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $endpoint = 'vat-number';
|
||||
|
||||
/**
|
||||
* Success Messages.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $messages = array();
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct() {
|
||||
|
||||
// New endpoint for vat-number WC >= 2.6.
|
||||
add_action( 'init', array( $this, 'add_endpoints' ) );
|
||||
add_filter( 'woocommerce_get_query_vars', array( $this, 'add_query_vars' ), 0 );
|
||||
|
||||
// Change My Account page title.
|
||||
add_filter( 'the_title', array( $this, 'endpoint_title' ) );
|
||||
|
||||
// Inserting new tab/page into My Account page.
|
||||
add_filter( 'woocommerce_account_menu_items', array( $this, 'new_menu_items' ) );
|
||||
add_action( 'woocommerce_account_' . $this->endpoint . '_endpoint', array( $this, 'endpoint_content' ) );
|
||||
|
||||
// Save a VAT number from My Account form if one is submitted.
|
||||
if ( isset( $_POST['action'] ) && 'edit_vat_number' === wc_clean( wp_unslash( $_POST['action'] ) ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Verifying nonce inside function.
|
||||
$this->save_vat_number();
|
||||
}
|
||||
|
||||
add_action( 'woocommerce_init', array( $this, 'maybe_remove_vat' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see if we need to remove vat from displaying in the cart and from product itself.
|
||||
*
|
||||
* @see https://github.com/woocommerce/woocommerce-eu-vat-number/issues/71
|
||||
* @see https://github.com/woocommerce/woocommerce-eu-vat-number/issues/74
|
||||
* @see https://github.com/woocommerce/woocommerce-eu-vat-number/issues/233
|
||||
*/
|
||||
public function maybe_remove_vat() {
|
||||
// Ignore checkout page as on checkout page VAT exempt based on VAT number from billing fields.
|
||||
if ( ( is_admin() && ! defined( 'DOING_AJAX' ) ) || ! wc_tax_enabled() || is_checkout() || ! is_user_logged_in() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$vat_number = get_user_meta( get_current_user_id(), 'vat_number', true );
|
||||
if ( empty( $vat_number ) || empty( WC()->customer ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Validate if VAT is valid. If valid, check for VAT exempt.
|
||||
try {
|
||||
$billing_country = WC()->customer->get_billing_country();
|
||||
$shipping_country = WC()->customer->get_shipping_country();
|
||||
|
||||
if ( $this->validate( $vat_number, $billing_country ) ) {
|
||||
WC_EU_VAT_Number::maybe_set_vat_exempt( true, $billing_country, $shipping_country );
|
||||
}
|
||||
} catch ( Exception $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
|
||||
// Ignore Exception.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register new endpoint to use inside My Account page.
|
||||
*
|
||||
* @since 2.1.12
|
||||
*
|
||||
* @see https://developer.wordpress.org/reference/functions/add_rewrite_endpoint/
|
||||
*/
|
||||
public function add_endpoints() {
|
||||
add_rewrite_endpoint( $this->endpoint, EP_ROOT | EP_PAGES );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add new query var.
|
||||
*
|
||||
* @since 2.1.12
|
||||
*
|
||||
* @param array $vars Query vars.
|
||||
* @return array
|
||||
*/
|
||||
public function add_query_vars( $vars ) {
|
||||
$vars[] = $this->endpoint;
|
||||
|
||||
return $vars;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set endpoint title.
|
||||
*
|
||||
* @since 2.1.12
|
||||
*
|
||||
* @param string $title Endpoint title.
|
||||
* @return string
|
||||
*/
|
||||
public function endpoint_title( $title ) {
|
||||
global $wp_query;
|
||||
|
||||
$is_endpoint = isset( $wp_query->query_vars[ $this->endpoint ] );
|
||||
|
||||
if ( $is_endpoint && ! is_admin() && is_main_query() && in_the_loop() && is_account_page() ) {
|
||||
$title = get_option( 'woocommerce_eu_vat_number_field_label', __( 'VAT number', 'woocommerce-eu-vat-number' ) );
|
||||
|
||||
remove_filter( 'the_title', array( $this, 'endpoint_title' ) );
|
||||
}
|
||||
|
||||
return $title;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert new endpoint into My Account menu.
|
||||
*
|
||||
* @since 2.1.12
|
||||
*
|
||||
* @param array $items Menu items.
|
||||
* @return array Menu items.
|
||||
*/
|
||||
public function new_menu_items( $items ) {
|
||||
// Remove logout menu item.
|
||||
$logout = $items['customer-logout'];
|
||||
unset( $items['customer-logout'] );
|
||||
|
||||
// Insert VAT Number.
|
||||
$items[ $this->endpoint ] = get_option( 'woocommerce_eu_vat_number_field_label', __( 'VAT number', 'woocommerce-eu-vat-number' ) );
|
||||
|
||||
// Insert back logout item.
|
||||
$items['customer-logout'] = $logout;
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Endpoint HTML content.
|
||||
*
|
||||
* @since 2.1.12
|
||||
*/
|
||||
public function endpoint_content() {
|
||||
$this->render_my_vat_number_content();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render My VAT Number content.
|
||||
*
|
||||
* @since 2.1.12
|
||||
*/
|
||||
public function render_my_vat_number_content() {
|
||||
$vars = array(
|
||||
'vat_number' => get_user_meta( get_current_user_id(), 'vat_number', true ),
|
||||
'messages' => $this->messages,
|
||||
);
|
||||
|
||||
wc_get_template(
|
||||
'my-account/my-vat-number.php',
|
||||
$vars,
|
||||
'woocommerce-eu-vat-number',
|
||||
untrailingslashit( plugin_dir_path( WC_EU_VAT_FILE ) ) . '/templates/'
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a VAT number.
|
||||
*
|
||||
* @version 2.3.0
|
||||
* @since 2.3.0
|
||||
* @param string $vat_number VAT number passed by the form.
|
||||
* @param string $billing_country Billing country of the order.
|
||||
* @param string $billing_postcode Billing postcode of the order.
|
||||
* @param string $current_vat VAT number saved in database.
|
||||
*
|
||||
* @return boolean
|
||||
* @throws Exception For invalid VAT Number.
|
||||
*/
|
||||
public function validate( $vat_number, $billing_country, $billing_postcode = '', $current_vat = '' ) {
|
||||
if ( empty( $vat_number ) ) {
|
||||
if ( empty( $current_vat ) ) {
|
||||
throw new Exception( __( 'VAT number cannot be empty.', 'woocommerce-eu-vat-number' ) );
|
||||
}
|
||||
// Allow empty input to clear VAT field.
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( empty( $billing_country ) ) {
|
||||
/* translators: 1: VAT Number */
|
||||
throw new Exception( sprintf( __( '%1$s can not be validated because the billing country is missing. Please update your billing address.', 'woocommerce-eu-vat-number' ), '<strong>' . get_option( 'woocommerce_eu_vat_number_field_label', __( 'VAT number', 'woocommerce-eu-vat-number' ) ) . '</strong>' ) );
|
||||
}
|
||||
|
||||
$valid = WC_EU_VAT_Number::vat_number_is_valid( $vat_number, $billing_country, $billing_postcode );
|
||||
|
||||
if ( is_wp_error( $valid ) ) {
|
||||
throw new Exception( $valid->get_error_message() );
|
||||
}
|
||||
|
||||
if ( ! $valid ) {
|
||||
// translators: %1$s VAT number field label, %2$s VAT number, %3$s Billing Country.
|
||||
throw new Exception( sprintf( __( 'You have entered an invalid %1$s (%2$s) for your billing country (%3$s).', 'woocommerce-eu-vat-number' ), get_option( 'woocommerce_eu_vat_number_field_label', __( 'VAT number', 'woocommerce-eu-vat-number' ) ), $vat_number, $billing_country ) );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to save VAT number from the my account form.
|
||||
*/
|
||||
public function save_vat_number() {
|
||||
if ( isset( $_POST['_wpnonce'] ) && wp_verify_nonce( wp_unslash( $_POST['_wpnonce'] ), 'woocommerce-edit_vat_number' ) ) { // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||||
try {
|
||||
$current_user_id = get_current_user_id();
|
||||
$vat_number = isset( $_POST['vat_number'] ) ? wc_clean( wp_unslash( $_POST['vat_number'] ) ) : '';
|
||||
$posted_vat = strtoupper( str_replace( array( ' ', '.', '-', ',', ', ' ), '', $vat_number ) );
|
||||
$user = get_userdata( $current_user_id );
|
||||
$current_vat = $user->vat_number;
|
||||
$billing_country = $user->billing_country;
|
||||
$billing_postcode = $user->billing_postcode;
|
||||
|
||||
$this->validate( $posted_vat, $billing_country, $billing_postcode, $current_vat );
|
||||
|
||||
update_user_meta( $current_user_id, 'vat_number', $posted_vat );
|
||||
update_user_meta( $current_user_id, 'billing_vat_number', $posted_vat );
|
||||
|
||||
if ( empty( $posted_vat ) ) {
|
||||
$message = __( 'VAT number removed successfully!', 'woocommerce-eu-vat-number' );
|
||||
} elseif ( empty( $current_vat ) ) {
|
||||
$message = __( 'VAT number saved successfully!', 'woocommerce-eu-vat-number' );
|
||||
} else {
|
||||
$message = __( 'VAT number updated successfully!', 'woocommerce-eu-vat-number' );
|
||||
}
|
||||
$this->messages = array( 'message' => $message, 'status' => 'info' );
|
||||
} catch ( Exception $e ) {
|
||||
$this->messages = array(
|
||||
'message' => $e->getMessage(),
|
||||
'status' => 'error',
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$wc_eu_vat_my_account = new WC_EU_VAT_My_Account();
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,293 +1,293 @@
|
|||
<?php
|
||||
/**
|
||||
* Handles EU VAT Number Privacy
|
||||
*
|
||||
* @package WooCommerce EU VAT Number
|
||||
*/
|
||||
|
||||
if ( ! class_exists( 'WC_Abstract_Privacy' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* EU VAT Privacy Class
|
||||
*/
|
||||
class WC_EU_VAT_Privacy extends WC_Abstract_Privacy {
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct( __( 'EU VAT', 'woocommerce-eu-vat-number' ), 5, 9 );
|
||||
|
||||
$this->add_exporter( 'woocommerce-eu-vat-number-order-data', __( 'WooCommerce EU VAT Order Data', 'woocommerce-eu-vat-number' ), array( $this, 'order_data_exporter' ) );
|
||||
$this->add_exporter( 'woocommerce-eu-vat-number-customer-data', __( 'WooCommerce EU VAT Customer Data', 'woocommerce-eu-vat-number' ), array( $this, 'customer_data_exporter' ) );
|
||||
|
||||
$this->add_eraser( 'woocommerce-eu-vat-number-customer-data', __( 'WooCommerce EU VAT Customer Data', 'woocommerce-eu-vat-number' ), array( $this, 'customer_data_eraser' ) );
|
||||
$this->add_eraser( 'woocommerce-eu-vat-number-order-data', __( 'WooCommerce EU VAT Order Data', 'woocommerce-eu-vat-number' ), array( $this, 'order_data_eraser' ) );
|
||||
|
||||
if ( class_exists( 'WC_Subscriptions' ) || class_exists( 'WC_Subscriptions_Core_Plugin' ) ) {
|
||||
$this->add_eraser( 'woocommerce-eu-vat-number-subscriptions-data', __( 'WooCommerce EU VAT Subscriptions Data', 'woocommerce-eu-vat-number' ), array( $this, 'subscriptions_data_eraser' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of orders.
|
||||
*
|
||||
* @param string $email_address Email address of customer.
|
||||
* @param int $page Current page.
|
||||
* @param string $post_type Default: order. Set to 'subscription' if querying for subscription orders.
|
||||
*
|
||||
* @return array WP_Post
|
||||
*/
|
||||
protected function get_orders( $email_address, $page, $post_type = 'order' ) {
|
||||
$user = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data.
|
||||
|
||||
// Default Query Args.
|
||||
$order_query = array(
|
||||
'status' => 'any',
|
||||
'limit' => 10,
|
||||
'page' => $page,
|
||||
);
|
||||
|
||||
// Additional query args to retrieve WooCommerce orders.
|
||||
if ( $user instanceof WP_User ) {
|
||||
$order_query['customer_id'] = (int) $user->ID;
|
||||
} else {
|
||||
$order_query['billing_email'] = $email_address;
|
||||
}
|
||||
|
||||
// Using wc_get_orders for WC orders & data store for subscriptions.
|
||||
if ( 'subscription' === $post_type ) {
|
||||
$result = WC_Data_Store::load( $post_type )->get_orders( $order_query );
|
||||
} else {
|
||||
$result = wc_get_orders( $order_query );
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the message of the privacy to display.
|
||||
*/
|
||||
public function get_privacy_message() {
|
||||
// translators: Privacy Docs URL.
|
||||
return wpautop( sprintf( __( 'By using this extension, you may be storing personal data or sharing data with an external service. <a href="%s" target="_blank">Learn more about how this works, including what you may want to include in your privacy policy.</a>', 'woocommerce-eu-vat-number' ), 'https://docs.woocommerce.com/document/marketplace-privacy/#woocommerce-eu-vat-number' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle exporting data for Orders.
|
||||
*
|
||||
* @param string $email_address E-mail address to export.
|
||||
* @param int $page Pagination of data.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function order_data_exporter( $email_address, $page = 1 ) {
|
||||
$done = false;
|
||||
$data_to_export = array();
|
||||
|
||||
$orders = $this->get_orders( $email_address, (int) $page );
|
||||
|
||||
$done = true;
|
||||
|
||||
if ( 0 < count( $orders ) ) {
|
||||
|
||||
/** @var \WC_Order $order */
|
||||
foreach ( $orders as $order ) {
|
||||
$data_to_export[] = array(
|
||||
'group_id' => 'woocommerce_orders',
|
||||
'group_label' => __( 'Orders', 'woocommerce-eu-vat-number' ),
|
||||
'item_id' => 'order-' . $order->get_id(),
|
||||
'data' => array(
|
||||
array(
|
||||
'name' => __( 'EU VAT number', 'woocommerce-eu-vat-number' ),
|
||||
'value' => $order->get_meta( '_vat_number', true ),
|
||||
),
|
||||
array(
|
||||
'name' => __( 'EU Billing VAT number', 'woocommerce-eu-vat-number' ),
|
||||
'value' => $order->get_meta( '_billing_vat_number', true ),
|
||||
),
|
||||
array(
|
||||
'name' => __( 'EU VAT country', 'woocommerce-eu-vat-number' ),
|
||||
'value' => $order->get_meta( '_customer_ip_country', true ),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
$done = 10 > count( $orders );
|
||||
}
|
||||
|
||||
return array(
|
||||
'data' => $data_to_export,
|
||||
'done' => $done,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds and exports customer data by email address.
|
||||
*
|
||||
* @since 3.4.0
|
||||
* @param string $email_address The user email address.
|
||||
* @param int $page Page.
|
||||
*
|
||||
* @return array An array of personal data in name value pairs
|
||||
*/
|
||||
public function customer_data_exporter( $email_address, $page ) {
|
||||
$user = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data.
|
||||
$data_to_export = array();
|
||||
|
||||
if ( $user instanceof WP_User ) {
|
||||
$data_to_export[] = array(
|
||||
'group_id' => 'woocommerce_customer',
|
||||
'group_label' => __( 'Customer Data', 'woocommerce-eu-vat-number' ),
|
||||
'item_id' => 'user',
|
||||
'data' => array(
|
||||
array(
|
||||
'name' => get_option( 'woocommerce_eu_vat_number_field_label', __( 'VAT number', 'woocommerce-eu-vat-number' ) ),
|
||||
'value' => get_user_meta( $user->ID, 'vat_number', true ),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return array(
|
||||
'data' => $data_to_export,
|
||||
'done' => true,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds and erases customer data by email address.
|
||||
*
|
||||
* @since 3.4.0
|
||||
* @param string $email_address The user email address.
|
||||
* @param int $page Page.
|
||||
*
|
||||
* @return array An array of personal data in name value pairs
|
||||
*/
|
||||
public function customer_data_eraser( $email_address, $page ) {
|
||||
$page = (int) $page;
|
||||
$user = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data.
|
||||
|
||||
$vat_number = get_user_meta( $user->ID, 'vat_number', true );
|
||||
|
||||
$items_removed = false;
|
||||
$messages = array();
|
||||
|
||||
if ( ! empty( $vat_number ) ) {
|
||||
$items_removed = true;
|
||||
delete_user_meta( $user->ID, 'vat_number' );
|
||||
$messages[] = __( 'EU VAT User Data Erased.', 'woocommerce-eu-vat-number' );
|
||||
}
|
||||
|
||||
return array(
|
||||
'items_removed' => $items_removed,
|
||||
'items_retained' => false,
|
||||
'messages' => $messages,
|
||||
'done' => true,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds and erases order data by email address.
|
||||
*
|
||||
* @since 3.4.0
|
||||
* @param string $email_address The user email address.
|
||||
* @param int $page Page.
|
||||
* @return array An array of personal data in name value pairs
|
||||
*/
|
||||
public function order_data_eraser( $email_address, $page ) {
|
||||
$orders = $this->get_orders( $email_address, (int) $page );
|
||||
return $this->maybe_erase_order_data( $orders );
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds and erases Subscription order data by email address.
|
||||
*
|
||||
* @since 2.3.26
|
||||
*
|
||||
* @param string $email_address The user email address.
|
||||
* @param int $page Page.
|
||||
* @return array An array of personal data in name value pairs.
|
||||
*/
|
||||
public function subscriptions_data_eraser( $email_address, $page ) {
|
||||
$subscriptions = $this->get_orders( $email_address, (int) $page, 'subscription' );
|
||||
return $this->maybe_erase_order_data( $subscriptions );
|
||||
}
|
||||
|
||||
/**
|
||||
* Erase EU VAT data from WooCommerce/Subscription orders.
|
||||
*
|
||||
* @since 2.3.26
|
||||
*
|
||||
* @param array $orders WooCommerce orders.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function maybe_erase_order_data( $orders ) {
|
||||
$items_removed = false;
|
||||
$items_retained = false;
|
||||
$messages = array();
|
||||
$done = true;
|
||||
|
||||
foreach ( (array) $orders as $order ) {
|
||||
list( $removed, $retained, $msgs ) = $this->maybe_handle_order( $order );
|
||||
|
||||
$items_removed |= $removed;
|
||||
$items_retained |= $retained;
|
||||
$messages = array_merge( $messages, $msgs );
|
||||
}
|
||||
|
||||
// Tell core if we have more orders to work on still.
|
||||
$done = count( $orders ) < 10;
|
||||
|
||||
return array(
|
||||
'items_removed' => $items_removed,
|
||||
'items_retained' => $items_retained,
|
||||
'messages' => $messages,
|
||||
'done' => $done,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle eraser of data tied to Orders
|
||||
*
|
||||
* @param WC_Order $order WooCommerce order/subscription object.
|
||||
*
|
||||
* @return array Array of order data removed/retained along with corresponding message.
|
||||
*/
|
||||
protected function maybe_handle_order( $order ) {
|
||||
$order_id = $order->get_id();
|
||||
$message = array();
|
||||
|
||||
$vat_number = $order->get_meta( '_billing_vat_number', true );
|
||||
$vat_number = ( ! empty( $vat_number ) ) ? $vat_number : $order->get_meta( '_vat_number', true ); // Compat with version < 2.3.21.
|
||||
$ip_country = $order->get_meta( '_customer_ip_country', true );
|
||||
|
||||
if ( empty( $vat_number ) && empty( $ip_country ) ) {
|
||||
return array( false, false, array() );
|
||||
}
|
||||
|
||||
$order->delete_meta_data( '_billing_vat_number' );
|
||||
$order->delete_meta_data( '_vat_number' ); // Compat with version < 2.3.21.
|
||||
$order->delete_meta_data( '_customer_ip_country' );
|
||||
|
||||
$order->save();
|
||||
|
||||
// Set default post type to 'order'.
|
||||
$post_type = 'order';
|
||||
|
||||
// Check whether the order is a subscription.
|
||||
if ( function_exists( 'wcs_is_subscription' ) && wcs_is_subscription( $order ) ) {
|
||||
$post_type = 'subscription';
|
||||
}
|
||||
|
||||
// translators: Post type, Order ID.
|
||||
$message[] = sprintf( __( 'Removed EU VAT data from %1$s %2$s.', 'woocommerce-eu-vat-number' ), $post_type, $order_id );
|
||||
|
||||
return array( true, false, $message );
|
||||
}
|
||||
}
|
||||
|
||||
new WC_EU_VAT_Privacy();
|
||||
<?php
|
||||
/**
|
||||
* Handles EU VAT Number Privacy
|
||||
*
|
||||
* @package WooCommerce EU VAT Number
|
||||
*/
|
||||
|
||||
if ( ! class_exists( 'WC_Abstract_Privacy' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* EU VAT Privacy Class
|
||||
*/
|
||||
class WC_EU_VAT_Privacy extends WC_Abstract_Privacy {
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct( __( 'EU VAT', 'woocommerce-eu-vat-number' ), 5, 9 );
|
||||
|
||||
$this->add_exporter( 'woocommerce-eu-vat-number-order-data', __( 'WooCommerce EU VAT Order Data', 'woocommerce-eu-vat-number' ), array( $this, 'order_data_exporter' ) );
|
||||
$this->add_exporter( 'woocommerce-eu-vat-number-customer-data', __( 'WooCommerce EU VAT Customer Data', 'woocommerce-eu-vat-number' ), array( $this, 'customer_data_exporter' ) );
|
||||
|
||||
$this->add_eraser( 'woocommerce-eu-vat-number-customer-data', __( 'WooCommerce EU VAT Customer Data', 'woocommerce-eu-vat-number' ), array( $this, 'customer_data_eraser' ) );
|
||||
$this->add_eraser( 'woocommerce-eu-vat-number-order-data', __( 'WooCommerce EU VAT Order Data', 'woocommerce-eu-vat-number' ), array( $this, 'order_data_eraser' ) );
|
||||
|
||||
if ( class_exists( 'WC_Subscriptions' ) || class_exists( 'WC_Subscriptions_Core_Plugin' ) ) {
|
||||
$this->add_eraser( 'woocommerce-eu-vat-number-subscriptions-data', __( 'WooCommerce EU VAT Subscriptions Data', 'woocommerce-eu-vat-number' ), array( $this, 'subscriptions_data_eraser' ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of orders.
|
||||
*
|
||||
* @param string $email_address Email address of customer.
|
||||
* @param int $page Current page.
|
||||
* @param string $post_type Default: order. Set to 'subscription' if querying for subscription orders.
|
||||
*
|
||||
* @return array WP_Post
|
||||
*/
|
||||
protected function get_orders( $email_address, $page, $post_type = 'order' ) {
|
||||
$user = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data.
|
||||
|
||||
// Default Query Args.
|
||||
$order_query = array(
|
||||
'status' => 'any',
|
||||
'limit' => 10,
|
||||
'page' => $page,
|
||||
);
|
||||
|
||||
// Additional query args to retrieve WooCommerce orders.
|
||||
if ( $user instanceof WP_User ) {
|
||||
$order_query['customer_id'] = (int) $user->ID;
|
||||
} else {
|
||||
$order_query['billing_email'] = $email_address;
|
||||
}
|
||||
|
||||
// Using wc_get_orders for WC orders & data store for subscriptions.
|
||||
if ( 'subscription' === $post_type ) {
|
||||
$result = WC_Data_Store::load( $post_type )->get_orders( $order_query );
|
||||
} else {
|
||||
$result = wc_get_orders( $order_query );
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the message of the privacy to display.
|
||||
*/
|
||||
public function get_privacy_message() {
|
||||
// translators: Privacy Docs URL.
|
||||
return wpautop( sprintf( __( 'By using this extension, you may be storing personal data or sharing data with an external service. <a href="%s" target="_blank">Learn more about how this works, including what you may want to include in your privacy policy.</a>', 'woocommerce-eu-vat-number' ), 'https://docs.woocommerce.com/document/marketplace-privacy/#woocommerce-eu-vat-number' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle exporting data for Orders.
|
||||
*
|
||||
* @param string $email_address E-mail address to export.
|
||||
* @param int $page Pagination of data.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function order_data_exporter( $email_address, $page = 1 ) {
|
||||
$done = false;
|
||||
$data_to_export = array();
|
||||
|
||||
$orders = $this->get_orders( $email_address, (int) $page );
|
||||
|
||||
$done = true;
|
||||
|
||||
if ( 0 < count( $orders ) ) {
|
||||
|
||||
/** @var \WC_Order $order */
|
||||
foreach ( $orders as $order ) {
|
||||
$data_to_export[] = array(
|
||||
'group_id' => 'woocommerce_orders',
|
||||
'group_label' => __( 'Orders', 'woocommerce-eu-vat-number' ),
|
||||
'item_id' => 'order-' . $order->get_id(),
|
||||
'data' => array(
|
||||
array(
|
||||
'name' => __( 'EU VAT number', 'woocommerce-eu-vat-number' ),
|
||||
'value' => $order->get_meta( '_vat_number', true ),
|
||||
),
|
||||
array(
|
||||
'name' => __( 'EU Billing VAT number', 'woocommerce-eu-vat-number' ),
|
||||
'value' => $order->get_meta( '_billing_vat_number', true ),
|
||||
),
|
||||
array(
|
||||
'name' => __( 'EU VAT country', 'woocommerce-eu-vat-number' ),
|
||||
'value' => $order->get_meta( '_customer_ip_country', true ),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
$done = 10 > count( $orders );
|
||||
}
|
||||
|
||||
return array(
|
||||
'data' => $data_to_export,
|
||||
'done' => $done,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds and exports customer data by email address.
|
||||
*
|
||||
* @since 3.4.0
|
||||
* @param string $email_address The user email address.
|
||||
* @param int $page Page.
|
||||
*
|
||||
* @return array An array of personal data in name value pairs
|
||||
*/
|
||||
public function customer_data_exporter( $email_address, $page ) {
|
||||
$user = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data.
|
||||
$data_to_export = array();
|
||||
|
||||
if ( $user instanceof WP_User ) {
|
||||
$data_to_export[] = array(
|
||||
'group_id' => 'woocommerce_customer',
|
||||
'group_label' => __( 'Customer Data', 'woocommerce-eu-vat-number' ),
|
||||
'item_id' => 'user',
|
||||
'data' => array(
|
||||
array(
|
||||
'name' => get_option( 'woocommerce_eu_vat_number_field_label', __( 'VAT number', 'woocommerce-eu-vat-number' ) ),
|
||||
'value' => get_user_meta( $user->ID, 'vat_number', true ),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return array(
|
||||
'data' => $data_to_export,
|
||||
'done' => true,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds and erases customer data by email address.
|
||||
*
|
||||
* @since 3.4.0
|
||||
* @param string $email_address The user email address.
|
||||
* @param int $page Page.
|
||||
*
|
||||
* @return array An array of personal data in name value pairs
|
||||
*/
|
||||
public function customer_data_eraser( $email_address, $page ) {
|
||||
$page = (int) $page;
|
||||
$user = get_user_by( 'email', $email_address ); // Check if user has an ID in the DB to load stored personal data.
|
||||
|
||||
$vat_number = get_user_meta( $user->ID, 'vat_number', true );
|
||||
|
||||
$items_removed = false;
|
||||
$messages = array();
|
||||
|
||||
if ( ! empty( $vat_number ) ) {
|
||||
$items_removed = true;
|
||||
delete_user_meta( $user->ID, 'vat_number' );
|
||||
$messages[] = __( 'EU VAT User Data Erased.', 'woocommerce-eu-vat-number' );
|
||||
}
|
||||
|
||||
return array(
|
||||
'items_removed' => $items_removed,
|
||||
'items_retained' => false,
|
||||
'messages' => $messages,
|
||||
'done' => true,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds and erases order data by email address.
|
||||
*
|
||||
* @since 3.4.0
|
||||
* @param string $email_address The user email address.
|
||||
* @param int $page Page.
|
||||
* @return array An array of personal data in name value pairs
|
||||
*/
|
||||
public function order_data_eraser( $email_address, $page ) {
|
||||
$orders = $this->get_orders( $email_address, (int) $page );
|
||||
return $this->maybe_erase_order_data( $orders );
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds and erases Subscription order data by email address.
|
||||
*
|
||||
* @since 2.3.26
|
||||
*
|
||||
* @param string $email_address The user email address.
|
||||
* @param int $page Page.
|
||||
* @return array An array of personal data in name value pairs.
|
||||
*/
|
||||
public function subscriptions_data_eraser( $email_address, $page ) {
|
||||
$subscriptions = $this->get_orders( $email_address, (int) $page, 'subscription' );
|
||||
return $this->maybe_erase_order_data( $subscriptions );
|
||||
}
|
||||
|
||||
/**
|
||||
* Erase EU VAT data from WooCommerce/Subscription orders.
|
||||
*
|
||||
* @since 2.3.26
|
||||
*
|
||||
* @param array $orders WooCommerce orders.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function maybe_erase_order_data( $orders ) {
|
||||
$items_removed = false;
|
||||
$items_retained = false;
|
||||
$messages = array();
|
||||
$done = true;
|
||||
|
||||
foreach ( (array) $orders as $order ) {
|
||||
list( $removed, $retained, $msgs ) = $this->maybe_handle_order( $order );
|
||||
|
||||
$items_removed |= $removed;
|
||||
$items_retained |= $retained;
|
||||
$messages = array_merge( $messages, $msgs );
|
||||
}
|
||||
|
||||
// Tell core if we have more orders to work on still.
|
||||
$done = count( $orders ) < 10;
|
||||
|
||||
return array(
|
||||
'items_removed' => $items_removed,
|
||||
'items_retained' => $items_retained,
|
||||
'messages' => $messages,
|
||||
'done' => $done,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle eraser of data tied to Orders
|
||||
*
|
||||
* @param WC_Order $order WooCommerce order/subscription object.
|
||||
*
|
||||
* @return array Array of order data removed/retained along with corresponding message.
|
||||
*/
|
||||
protected function maybe_handle_order( $order ) {
|
||||
$order_id = $order->get_id();
|
||||
$message = array();
|
||||
|
||||
$vat_number = $order->get_meta( '_billing_vat_number', true );
|
||||
$vat_number = ( ! empty( $vat_number ) ) ? $vat_number : $order->get_meta( '_vat_number', true ); // Compat with version < 2.3.21.
|
||||
$ip_country = $order->get_meta( '_customer_ip_country', true );
|
||||
|
||||
if ( empty( $vat_number ) && empty( $ip_country ) ) {
|
||||
return array( false, false, array() );
|
||||
}
|
||||
|
||||
$order->delete_meta_data( '_billing_vat_number' );
|
||||
$order->delete_meta_data( '_vat_number' ); // Compat with version < 2.3.21.
|
||||
$order->delete_meta_data( '_customer_ip_country' );
|
||||
|
||||
$order->save();
|
||||
|
||||
// Set default post type to 'order'.
|
||||
$post_type = 'order';
|
||||
|
||||
// Check whether the order is a subscription.
|
||||
if ( function_exists( 'wcs_is_subscription' ) && wcs_is_subscription( $order ) ) {
|
||||
$post_type = 'subscription';
|
||||
}
|
||||
|
||||
// translators: Post type, Order ID.
|
||||
$message[] = sprintf( __( 'Removed EU VAT data from %1$s %2$s.', 'woocommerce-eu-vat-number' ), $post_type, $order_id );
|
||||
|
||||
return array( true, false, $message );
|
||||
}
|
||||
}
|
||||
|
||||
new WC_EU_VAT_Privacy();
|
||||
|
|
|
@ -1,244 +1,244 @@
|
|||
<?php
|
||||
/**
|
||||
* EC Sales List Report.
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
* @phpcs:disable WordPress.DateTime.RestrictedFunctions.date_date
|
||||
* @phpcs:disable WordPress.DateTime.CurrentTimeTimestamp.Requested
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_EU_VAT_Report_EC_Sales_List class
|
||||
*/
|
||||
class WC_EU_VAT_Report_EC_Sales_List extends WC_Admin_Report {
|
||||
|
||||
/**
|
||||
* Get the legend for the main chart sidebar
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_chart_legend() {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Output an export link
|
||||
*/
|
||||
public function get_export_button() {
|
||||
$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : 'last_month'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
?>
|
||||
<a
|
||||
href="#"
|
||||
download="report-<?php echo esc_attr( $current_range ); ?>-<?php echo esc_attr( date_i18n( 'Y-m-d', current_time( 'timestamp' ) ) ); ?>.csv"
|
||||
class="export_csv"
|
||||
data-export="table"
|
||||
>
|
||||
<?php esc_html_e( 'Export CSV', 'woocommerce-eu-vat-number' ); ?>
|
||||
</a>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the report
|
||||
*/
|
||||
public function output_report() {
|
||||
$ranges = array(
|
||||
'prev_quarter' => __( 'Previous Quarter', 'woocommerce-eu-vat-number' ),
|
||||
'last_quarter' => __( 'Last Quarter', 'woocommerce-eu-vat-number' ),
|
||||
'quarter' => __( 'This Quarter', 'woocommerce-eu-vat-number' ),
|
||||
);
|
||||
|
||||
$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : 'quarter'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
|
||||
if ( ! in_array( $current_range, array( 'custom', 'prev_quarter', 'last_quarter', 'quarter' ), true ) ) {
|
||||
$current_range = 'quarter';
|
||||
}
|
||||
|
||||
$this->calculate_current_range( $current_range );
|
||||
|
||||
$hide_sidebar = true;
|
||||
|
||||
include WC()->plugin_path() . '/includes/admin/views/html-report-by-date.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current range and calculate the start and end dates
|
||||
*
|
||||
* @param string $current_range Report Range.
|
||||
*/
|
||||
public function calculate_current_range( $current_range ) {
|
||||
$this->chart_groupby = 'month';
|
||||
$quarter = absint( ceil( date( 'm', current_time( 'timestamp' ) ) / 3 ) );
|
||||
$year = absint( date( 'Y', current_time( 'timestamp' ) ) );
|
||||
|
||||
switch ( $current_range ) {
|
||||
case 'prev_quarter':
|
||||
$quarter = $quarter - 2;
|
||||
if ( 0 === $quarter ) {
|
||||
$quarter = 4;
|
||||
$year --;
|
||||
} elseif ( -1 === $quarter ) {
|
||||
$quarter = 3;
|
||||
$year --;
|
||||
}
|
||||
break;
|
||||
case 'last_quarter':
|
||||
--$quarter;
|
||||
if ( 0 === $quarter ) {
|
||||
$quarter = 4;
|
||||
$year --;
|
||||
}
|
||||
break;
|
||||
case 'custom':
|
||||
parent::calculate_current_range( $current_range );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 1 === $quarter ) {
|
||||
$this->start_date = strtotime( $year . '-01-01' );
|
||||
$this->end_date = strtotime( date( 'Y-m-t', strtotime( $year . '-03-01' ) ) );
|
||||
} elseif ( 2 === $quarter ) {
|
||||
$this->start_date = strtotime( $year . '-04-01' );
|
||||
$this->end_date = strtotime( date( 'Y-m-t', strtotime( $year . '-06-01' ) ) );
|
||||
} elseif ( 3 === $quarter ) {
|
||||
$this->start_date = strtotime( $year . '-07-01' );
|
||||
$this->end_date = strtotime( date( 'Y-m-t', strtotime( $year . '-09-01' ) ) );
|
||||
} elseif ( 4 === $quarter ) {
|
||||
$this->start_date = strtotime( $year . '-10-01' );
|
||||
$this->end_date = strtotime( date( 'Y-m-t', strtotime( $year . '-12-01' ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the main chart
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function get_main_chart() {
|
||||
$ec_sales1 = $this->get_order_report_data(
|
||||
array(
|
||||
'data' => array(
|
||||
'_order_total' => array(
|
||||
'type' => 'meta',
|
||||
'function' => 'SUM',
|
||||
'name' => 'total_sales',
|
||||
),
|
||||
'_billing_vat_number' => array(
|
||||
'type' => 'meta',
|
||||
'function' => '',
|
||||
'name' => '_billing_vat_number',
|
||||
),
|
||||
'_billing_country' => array(
|
||||
'type' => 'meta',
|
||||
'function' => '',
|
||||
'name' => '_billing_country',
|
||||
),
|
||||
'_order_currency' => array(
|
||||
'type' => 'meta',
|
||||
'function' => '',
|
||||
'name' => '_order_currency',
|
||||
),
|
||||
),
|
||||
'where' => array(
|
||||
array(
|
||||
'key' => 'meta__billing_country.meta_value',
|
||||
'value' => WC_EU_VAT_Number::get_eu_countries(),
|
||||
'operator' => 'in',
|
||||
),
|
||||
array(
|
||||
'key' => 'meta__billing_vat_number.meta_value',
|
||||
'value' => '',
|
||||
'operator' => '!=',
|
||||
),
|
||||
),
|
||||
'group_by' => '_billing_vat_number',
|
||||
'order_by' => '_billing_vat_number ASC',
|
||||
'query_type' => 'get_results',
|
||||
'order_status' => array( 'completed' ),
|
||||
'filter_range' => true,
|
||||
)
|
||||
);
|
||||
$ec_sales2 = $this->get_order_report_data(
|
||||
array(
|
||||
'data' => array(
|
||||
'_order_total' => array(
|
||||
'type' => 'meta',
|
||||
'function' => 'SUM',
|
||||
'name' => 'total_sales',
|
||||
),
|
||||
'_vat_number' => array(
|
||||
'type' => 'meta',
|
||||
'function' => '',
|
||||
'name' => '_vat_number',
|
||||
),
|
||||
'_billing_country' => array(
|
||||
'type' => 'meta',
|
||||
'function' => '',
|
||||
'name' => '_billing_country',
|
||||
),
|
||||
'_order_currency' => array(
|
||||
'type' => 'meta',
|
||||
'function' => '',
|
||||
'name' => '_order_currency',
|
||||
),
|
||||
),
|
||||
'where' => array(
|
||||
array(
|
||||
'key' => 'meta__billing_country.meta_value',
|
||||
'value' => WC_EU_VAT_Number::get_eu_countries(),
|
||||
'operator' => 'in',
|
||||
),
|
||||
array(
|
||||
'key' => 'meta__vat_number.meta_value',
|
||||
'value' => '',
|
||||
'operator' => '!=',
|
||||
),
|
||||
),
|
||||
'group_by' => '_vat_number',
|
||||
'order_by' => '_vat_number ASC',
|
||||
'query_type' => 'get_results',
|
||||
'order_status' => array( 'completed' ),
|
||||
'filter_range' => true,
|
||||
)
|
||||
);
|
||||
|
||||
$ec_sales = array_merge( $ec_sales1, $ec_sales2 );
|
||||
?>
|
||||
<table class="widefat">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?php esc_html_e( 'Country', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th><?php echo esc_html( get_option( 'woocommerce_eu_vat_number_field_label', __( 'VAT number', 'woocommerce-eu-vat-number' ) ) ); ?></th>
|
||||
<th class="total_row"><?php esc_html_e( 'Value', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<?php if ( $ec_sales ) : ?>
|
||||
<tbody>
|
||||
<?php
|
||||
foreach ( $ec_sales as $ec_sale ) {
|
||||
$vat_number = ! empty( $ec_sale->_billing_vat_number ) ? $ec_sale->_billing_vat_number : $ec_sale->_vat_number;
|
||||
?>
|
||||
<tr>
|
||||
<th scope="row"><?php echo esc_html( $ec_sale->_billing_country ); ?></th>
|
||||
<th scope="row"><?php echo esc_html( str_replace( $ec_sale->_billing_country, '', $vat_number ) ); ?></th>
|
||||
<th scope="row"><?php echo wc_price( $ec_sale->total_sales, array( 'currency', $ec_sale->_order_currency ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></th>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
<?php else : ?>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="3"><?php esc_html_e( 'No B2B EU orders found within this period.', 'woocommerce-eu-vat-number' ); ?></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<?php endif; ?>
|
||||
</table>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
<?php
|
||||
/**
|
||||
* EC Sales List Report.
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
* @phpcs:disable WordPress.DateTime.RestrictedFunctions.date_date
|
||||
* @phpcs:disable WordPress.DateTime.CurrentTimeTimestamp.Requested
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_EU_VAT_Report_EC_Sales_List class
|
||||
*/
|
||||
class WC_EU_VAT_Report_EC_Sales_List extends WC_Admin_Report {
|
||||
|
||||
/**
|
||||
* Get the legend for the main chart sidebar
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_chart_legend() {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Output an export link
|
||||
*/
|
||||
public function get_export_button() {
|
||||
$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : 'last_month'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
?>
|
||||
<a
|
||||
href="#"
|
||||
download="report-<?php echo esc_attr( $current_range ); ?>-<?php echo esc_attr( date_i18n( 'Y-m-d', current_time( 'timestamp' ) ) ); ?>.csv"
|
||||
class="export_csv"
|
||||
data-export="table"
|
||||
>
|
||||
<?php esc_html_e( 'Export CSV', 'woocommerce-eu-vat-number' ); ?>
|
||||
</a>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the report
|
||||
*/
|
||||
public function output_report() {
|
||||
$ranges = array(
|
||||
'prev_quarter' => __( 'Previous Quarter', 'woocommerce-eu-vat-number' ),
|
||||
'last_quarter' => __( 'Last Quarter', 'woocommerce-eu-vat-number' ),
|
||||
'quarter' => __( 'This Quarter', 'woocommerce-eu-vat-number' ),
|
||||
);
|
||||
|
||||
$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : 'quarter'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
|
||||
if ( ! in_array( $current_range, array( 'custom', 'prev_quarter', 'last_quarter', 'quarter' ), true ) ) {
|
||||
$current_range = 'quarter';
|
||||
}
|
||||
|
||||
$this->calculate_current_range( $current_range );
|
||||
|
||||
$hide_sidebar = true;
|
||||
|
||||
include WC()->plugin_path() . '/includes/admin/views/html-report-by-date.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current range and calculate the start and end dates
|
||||
*
|
||||
* @param string $current_range Report Range.
|
||||
*/
|
||||
public function calculate_current_range( $current_range ) {
|
||||
$this->chart_groupby = 'month';
|
||||
$quarter = absint( ceil( date( 'm', current_time( 'timestamp' ) ) / 3 ) );
|
||||
$year = absint( date( 'Y', current_time( 'timestamp' ) ) );
|
||||
|
||||
switch ( $current_range ) {
|
||||
case 'prev_quarter':
|
||||
$quarter = $quarter - 2;
|
||||
if ( 0 === $quarter ) {
|
||||
$quarter = 4;
|
||||
$year --;
|
||||
} elseif ( -1 === $quarter ) {
|
||||
$quarter = 3;
|
||||
$year --;
|
||||
}
|
||||
break;
|
||||
case 'last_quarter':
|
||||
--$quarter;
|
||||
if ( 0 === $quarter ) {
|
||||
$quarter = 4;
|
||||
$year --;
|
||||
}
|
||||
break;
|
||||
case 'custom':
|
||||
parent::calculate_current_range( $current_range );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 1 === $quarter ) {
|
||||
$this->start_date = strtotime( $year . '-01-01' );
|
||||
$this->end_date = strtotime( date( 'Y-m-t', strtotime( $year . '-03-01' ) ) );
|
||||
} elseif ( 2 === $quarter ) {
|
||||
$this->start_date = strtotime( $year . '-04-01' );
|
||||
$this->end_date = strtotime( date( 'Y-m-t', strtotime( $year . '-06-01' ) ) );
|
||||
} elseif ( 3 === $quarter ) {
|
||||
$this->start_date = strtotime( $year . '-07-01' );
|
||||
$this->end_date = strtotime( date( 'Y-m-t', strtotime( $year . '-09-01' ) ) );
|
||||
} elseif ( 4 === $quarter ) {
|
||||
$this->start_date = strtotime( $year . '-10-01' );
|
||||
$this->end_date = strtotime( date( 'Y-m-t', strtotime( $year . '-12-01' ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the main chart
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function get_main_chart() {
|
||||
$ec_sales1 = $this->get_order_report_data(
|
||||
array(
|
||||
'data' => array(
|
||||
'_order_total' => array(
|
||||
'type' => 'meta',
|
||||
'function' => 'SUM',
|
||||
'name' => 'total_sales',
|
||||
),
|
||||
'_billing_vat_number' => array(
|
||||
'type' => 'meta',
|
||||
'function' => '',
|
||||
'name' => '_billing_vat_number',
|
||||
),
|
||||
'_billing_country' => array(
|
||||
'type' => 'meta',
|
||||
'function' => '',
|
||||
'name' => '_billing_country',
|
||||
),
|
||||
'_order_currency' => array(
|
||||
'type' => 'meta',
|
||||
'function' => '',
|
||||
'name' => '_order_currency',
|
||||
),
|
||||
),
|
||||
'where' => array(
|
||||
array(
|
||||
'key' => 'meta__billing_country.meta_value',
|
||||
'value' => WC_EU_VAT_Number::get_eu_countries(),
|
||||
'operator' => 'in',
|
||||
),
|
||||
array(
|
||||
'key' => 'meta__billing_vat_number.meta_value',
|
||||
'value' => '',
|
||||
'operator' => '!=',
|
||||
),
|
||||
),
|
||||
'group_by' => '_billing_vat_number',
|
||||
'order_by' => '_billing_vat_number ASC',
|
||||
'query_type' => 'get_results',
|
||||
'order_status' => array( 'completed' ),
|
||||
'filter_range' => true,
|
||||
)
|
||||
);
|
||||
$ec_sales2 = $this->get_order_report_data(
|
||||
array(
|
||||
'data' => array(
|
||||
'_order_total' => array(
|
||||
'type' => 'meta',
|
||||
'function' => 'SUM',
|
||||
'name' => 'total_sales',
|
||||
),
|
||||
'_vat_number' => array(
|
||||
'type' => 'meta',
|
||||
'function' => '',
|
||||
'name' => '_vat_number',
|
||||
),
|
||||
'_billing_country' => array(
|
||||
'type' => 'meta',
|
||||
'function' => '',
|
||||
'name' => '_billing_country',
|
||||
),
|
||||
'_order_currency' => array(
|
||||
'type' => 'meta',
|
||||
'function' => '',
|
||||
'name' => '_order_currency',
|
||||
),
|
||||
),
|
||||
'where' => array(
|
||||
array(
|
||||
'key' => 'meta__billing_country.meta_value',
|
||||
'value' => WC_EU_VAT_Number::get_eu_countries(),
|
||||
'operator' => 'in',
|
||||
),
|
||||
array(
|
||||
'key' => 'meta__vat_number.meta_value',
|
||||
'value' => '',
|
||||
'operator' => '!=',
|
||||
),
|
||||
),
|
||||
'group_by' => '_vat_number',
|
||||
'order_by' => '_vat_number ASC',
|
||||
'query_type' => 'get_results',
|
||||
'order_status' => array( 'completed' ),
|
||||
'filter_range' => true,
|
||||
)
|
||||
);
|
||||
|
||||
$ec_sales = array_merge( $ec_sales1, $ec_sales2 );
|
||||
?>
|
||||
<table class="widefat">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?php esc_html_e( 'Country', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th><?php echo esc_html( get_option( 'woocommerce_eu_vat_number_field_label', __( 'VAT number', 'woocommerce-eu-vat-number' ) ) ); ?></th>
|
||||
<th class="total_row"><?php esc_html_e( 'Value', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<?php if ( $ec_sales ) : ?>
|
||||
<tbody>
|
||||
<?php
|
||||
foreach ( $ec_sales as $ec_sale ) {
|
||||
$vat_number = ! empty( $ec_sale->_billing_vat_number ) ? $ec_sale->_billing_vat_number : $ec_sale->_vat_number;
|
||||
?>
|
||||
<tr>
|
||||
<th scope="row"><?php echo esc_html( $ec_sale->_billing_country ); ?></th>
|
||||
<th scope="row"><?php echo esc_html( str_replace( $ec_sale->_billing_country, '', $vat_number ) ); ?></th>
|
||||
<th scope="row"><?php echo wc_price( $ec_sale->total_sales, array( 'currency', $ec_sale->_order_currency ) ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></th>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
<?php else : ?>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td colspan="3"><?php esc_html_e( 'No B2B EU orders found within this period.', 'woocommerce-eu-vat-number' ); ?></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<?php endif; ?>
|
||||
</table>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,409 +1,409 @@
|
|||
<?php
|
||||
/**
|
||||
* EU VAT Report
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
* @phpcs:disable WordPress.DateTime.RestrictedFunctions.date_date
|
||||
* @phpcs:disable WordPress.DateTime.CurrentTimeTimestamp.Requested
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_EU_VAT_Report_B2C_Sales class
|
||||
*/
|
||||
class WC_EU_VAT_Report_EU_VAT extends WC_Admin_Report {
|
||||
|
||||
/**
|
||||
* Get the legend for the main chart sidebar.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_chart_legend() {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Output an export link
|
||||
*/
|
||||
public function get_export_button() {
|
||||
$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : 'last_month'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
?>
|
||||
<a
|
||||
href="#"
|
||||
download="report-<?php echo esc_attr( $current_range ); ?>-<?php echo esc_attr( date_i18n( 'Y-m-d', current_time( 'timestamp' ) ) ); ?>.csv"
|
||||
class="export_csv"
|
||||
data-export="table"
|
||||
>
|
||||
<?php esc_html_e( 'Export CSV', 'woocommerce-eu-vat-number' ); ?>
|
||||
</a>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the report
|
||||
*/
|
||||
public function output_report() {
|
||||
$ranges = array(
|
||||
'prev_quarter' => __( 'Previous Quarter', 'woocommerce-eu-vat-number' ),
|
||||
'last_quarter' => __( 'Last Quarter', 'woocommerce-eu-vat-number' ),
|
||||
'quarter' => __( 'This Quarter', 'woocommerce-eu-vat-number' ),
|
||||
);
|
||||
|
||||
$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : 'quarter'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
|
||||
if ( ! in_array( $current_range, array( 'custom', 'prev_quarter', 'last_quarter', 'quarter' ), true ) ) {
|
||||
$current_range = 'quarter';
|
||||
}
|
||||
|
||||
$this->calculate_current_range( $current_range );
|
||||
|
||||
$hide_sidebar = true;
|
||||
|
||||
include WC()->plugin_path() . '/includes/admin/views/html-report-by-date.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current range and calculate the start and end dates
|
||||
*
|
||||
* @param string $current_range Report Range.
|
||||
*/
|
||||
public function calculate_current_range( $current_range ) {
|
||||
$this->chart_groupby = 'month';
|
||||
$quarter = absint( ceil( date( 'm', current_time( 'timestamp' ) ) / 3 ) );
|
||||
$year = absint( date( 'Y', current_time( 'timestamp' ) ) );
|
||||
|
||||
switch ( $current_range ) {
|
||||
case 'prev_quarter':
|
||||
$quarter = $quarter - 2;
|
||||
if ( 0 === $quarter ) {
|
||||
$quarter = 4;
|
||||
$year --;
|
||||
} elseif ( -1 === $quarter ) {
|
||||
$quarter = 3;
|
||||
$year --;
|
||||
}
|
||||
break;
|
||||
case 'last_quarter':
|
||||
--$quarter;
|
||||
if ( 0 === $quarter ) {
|
||||
$quarter = 4;
|
||||
$year --;
|
||||
}
|
||||
break;
|
||||
case 'custom':
|
||||
parent::calculate_current_range( $current_range );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 1 === $quarter ) {
|
||||
$this->start_date = strtotime( $year . '-01-01' );
|
||||
$this->end_date = strtotime( date( 'Y-m-t', strtotime( $year . '-03-01' ) ) );
|
||||
} elseif ( 2 === $quarter ) {
|
||||
$this->start_date = strtotime( $year . '-04-01' );
|
||||
$this->end_date = strtotime( date( 'Y-m-t', strtotime( $year . '-06-01' ) ) );
|
||||
} elseif ( 3 === $quarter ) {
|
||||
$this->start_date = strtotime( $year . '-07-01' );
|
||||
$this->end_date = strtotime( date( 'Y-m-t', strtotime( $year . '-09-01' ) ) );
|
||||
} elseif ( 4 === $quarter ) {
|
||||
$this->start_date = strtotime( $year . '-10-01' );
|
||||
$this->end_date = strtotime( date( 'Y-m-t', strtotime( $year . '-12-01' ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the main chart
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function get_main_chart() {
|
||||
global $wpdb;
|
||||
|
||||
$debug = false;
|
||||
|
||||
// If debug is enabled, don't use cached data.
|
||||
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
|
||||
$debug = true;
|
||||
}
|
||||
|
||||
$line_data = $this->get_order_report_data(
|
||||
array(
|
||||
'data' => array(
|
||||
'_line_total' => array(
|
||||
'type' => 'order_item_meta',
|
||||
'order_item_type' => '',
|
||||
'function' => '',
|
||||
'name' => '_line_total',
|
||||
),
|
||||
'_line_tax_data' => array(
|
||||
'type' => 'order_item_meta',
|
||||
'order_item_type' => '',
|
||||
'function' => '',
|
||||
'name' => '_line_tax_data',
|
||||
),
|
||||
'ID' => array(
|
||||
'type' => 'post_data',
|
||||
'function' => '',
|
||||
'name' => 'refund_id',
|
||||
),
|
||||
),
|
||||
'filter_range' => true,
|
||||
'query_type' => 'get_results',
|
||||
'group_by' => '',
|
||||
'order_types' => array( 'shop_order', 'shop_order_refund' ),
|
||||
'order_status' => array( 'completed', 'refunded' ),
|
||||
'nocache' => $debug,
|
||||
)
|
||||
);
|
||||
|
||||
$grouped_tax_rows = array();
|
||||
|
||||
foreach ( $line_data as $data ) {
|
||||
$line_total = $data->_line_total;
|
||||
$line_tax_data = maybe_unserialize( $data->_line_tax_data );
|
||||
|
||||
foreach ( $line_tax_data['total'] as $tax_id => $tax_value ) {
|
||||
if ( ! isset( $grouped_tax_rows[ $tax_id ] ) ) {
|
||||
$grouped_tax_rows[ $tax_id ] = (object) array(
|
||||
'amount' => 0,
|
||||
'refunded_amount' => 0,
|
||||
'tax_amount' => 0,
|
||||
'refunded_tax_amount' => 0,
|
||||
);
|
||||
}
|
||||
|
||||
if ( $line_total < 0 ) {
|
||||
$grouped_tax_rows[ $tax_id ]->refunded_amount += $line_total;
|
||||
} else {
|
||||
$grouped_tax_rows[ $tax_id ]->amount += $line_total;
|
||||
}
|
||||
|
||||
if ( $tax_value < 0 ) {
|
||||
$grouped_tax_rows[ $tax_id ]->refunded_tax_amount += wc_round_tax_total( $tax_value );
|
||||
} else {
|
||||
$grouped_tax_rows[ $tax_id ]->tax_amount += wc_round_tax_total( $tax_value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$refunded_line_data = $this->get_order_report_data(
|
||||
array(
|
||||
'data' => array(
|
||||
'_line_total' => array(
|
||||
'type' => 'order_item_meta',
|
||||
'order_item_type' => '',
|
||||
'function' => '',
|
||||
'name' => '_line_total',
|
||||
),
|
||||
'_line_tax_data' => array(
|
||||
'type' => 'order_item_meta',
|
||||
'order_item_type' => '',
|
||||
'function' => '',
|
||||
'name' => '_line_tax_data',
|
||||
),
|
||||
),
|
||||
'filter_range' => true,
|
||||
'query_type' => 'get_results',
|
||||
'group_by' => '',
|
||||
'order_types' => array( 'shop_order', 'shop_order_refund' ),
|
||||
'order_status' => array( 'refunded' ),
|
||||
'nocache' => $debug,
|
||||
)
|
||||
);
|
||||
|
||||
foreach ( $refunded_line_data as $data ) {
|
||||
$line_total = $data->_line_total;
|
||||
$line_tax_data = maybe_unserialize( $data->_line_tax_data );
|
||||
|
||||
foreach ( $line_tax_data['total'] as $tax_id => $tax_value ) {
|
||||
if ( ! isset( $grouped_tax_rows[ $tax_id ] ) ) {
|
||||
$grouped_tax_rows[ $tax_id ] = (object) array(
|
||||
'amount' => 0,
|
||||
'refunded_amount' => 0,
|
||||
'tax_amount' => 0,
|
||||
'refunded_tax_amount' => 0,
|
||||
);
|
||||
}
|
||||
|
||||
$grouped_tax_rows[ $tax_id ]->refunded_amount += ( $line_total * -1 );
|
||||
$grouped_tax_rows[ $tax_id ]->refunded_tax_amount += wc_round_tax_total( (float) $tax_value * -1 );
|
||||
}
|
||||
}
|
||||
|
||||
$shipping_tax_amount = $this->get_order_report_data(
|
||||
array(
|
||||
'data' => array(
|
||||
'rate_id' => array(
|
||||
'type' => 'order_item_meta',
|
||||
'order_item_type' => '',
|
||||
'function' => '',
|
||||
'name' => 'rate_id',
|
||||
),
|
||||
'shipping_tax_amount' => array(
|
||||
'type' => 'order_item_meta',
|
||||
'order_item_type' => 'tax',
|
||||
'function' => '',
|
||||
'name' => 'shipping_tax_amount',
|
||||
),
|
||||
),
|
||||
'filter_range' => true,
|
||||
'query_type' => 'get_results',
|
||||
'group_by' => '',
|
||||
'order_types' => array( 'shop_order', 'shop_order_refund' ),
|
||||
'order_status' => array( 'completed' ),
|
||||
'nocache' => $debug,
|
||||
)
|
||||
);
|
||||
|
||||
foreach ( $shipping_tax_amount as $data ) {
|
||||
$tax_value = $data->shipping_tax_amount;
|
||||
$tax_id = $data->rate_id;
|
||||
|
||||
if ( ! isset( $grouped_tax_rows[ $tax_id ] ) ) {
|
||||
$grouped_tax_rows[ $tax_id ] = (object) array(
|
||||
'amount' => 0,
|
||||
'refunded_amount' => 0,
|
||||
'tax_amount' => 0,
|
||||
'refunded_tax_amount' => 0,
|
||||
);
|
||||
}
|
||||
|
||||
$grouped_tax_rows[ $tax_id ]->tax_amount += wc_round_tax_total( $tax_value );
|
||||
}
|
||||
|
||||
$refund_amounts = $this->get_order_report_data(
|
||||
array(
|
||||
'data' => array(
|
||||
'ID' => array(
|
||||
'type' => 'post_data',
|
||||
'function' => '',
|
||||
'name' => 'refund_id',
|
||||
),
|
||||
'post_parent' => array(
|
||||
'type' => 'post_data',
|
||||
'function' => '',
|
||||
'name' => 'order_id',
|
||||
),
|
||||
'_refund_amount' => array(
|
||||
'type' => 'meta',
|
||||
'function' => '',
|
||||
'name' => 'total_refund',
|
||||
),
|
||||
),
|
||||
'group_by' => 'refund_id',
|
||||
'query_type' => 'get_results',
|
||||
'filter_range' => true,
|
||||
'order_status' => false,
|
||||
'parent_order_status' => array( 'completed', 'processing', 'on-hold' ),
|
||||
'nocache' => $debug,
|
||||
)
|
||||
);
|
||||
|
||||
foreach ( $refund_amounts as $refund_data ) {
|
||||
$order = wc_get_order( $refund_data->order_id );
|
||||
|
||||
if ( is_object( $order ) ) {
|
||||
$cached_results = get_transient( strtolower( get_class( $this ) . '_' . $refund_data->order_id ) );
|
||||
|
||||
if ( false === $cached_results ) {
|
||||
$cached_results = $wpdb->get_var( $wpdb->prepare( "SELECT meta_value FROM {$wpdb->prefix}woocommerce_order_itemmeta AS order_itemmeta LEFT JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON order_itemmeta.order_item_id = order_items.order_item_id WHERE order_items.order_id = %d AND order_items.order_item_type = %s AND order_itemmeta.meta_key = %s", $refund_data->order_id, 'tax', 'rate_id' ) );
|
||||
|
||||
set_transient( strtolower( get_class( $this ) . '_' . $refund_data->order_id ), $cached_results, DAY_IN_SECONDS );
|
||||
}
|
||||
|
||||
$tax_id = $cached_results;
|
||||
|
||||
if ( isset( $grouped_tax_rows[ $tax_id ] ) ) {
|
||||
|
||||
$total_refund = $refund_data->total_refund;
|
||||
|
||||
// Subtract any line items from this total.
|
||||
foreach ( $line_data as $data ) {
|
||||
if ( $refund_data->refund_id === $data->refund_id ) {
|
||||
$total_refund += $data->_line_total;
|
||||
$line_tax_data = maybe_unserialize( $data->_line_tax_data );
|
||||
|
||||
foreach ( $line_tax_data['total'] as $tax_id => $tax_value ) {
|
||||
$total_refund += wc_round_tax_total( $tax_value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$grouped_tax_rows[ $tax_id ]->refunded_amount += -$total_refund;
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
<table class="widefat">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?php esc_html_e( 'Country', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th><?php esc_html_e( 'Code', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th><?php esc_html_e( 'Tax Rate', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th class="total_row"><?php esc_html_e( 'Amount', 'woocommerce-eu-vat-number-eu-vat' ); ?></th>
|
||||
<th class="total_row"><?php esc_html_e( 'Refunded Amount', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th class="total_row"><?php esc_html_e( 'Final Amount', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th class="total_row"><?php esc_html_e( 'Tax Amount', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th class="total_row"><?php esc_html_e( 'Tax Refunded Amount', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th class="total_row"><?php esc_html_e( 'Final Tax Amount ', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<?php if ( $grouped_tax_rows ) : ?>
|
||||
<tbody>
|
||||
<?php
|
||||
foreach ( $grouped_tax_rows as $rate_id => $tax_row ) {
|
||||
$rate = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_id = %d;", $rate_id ) );
|
||||
|
||||
if ( ! is_object( $rate ) || ! in_array( $rate->tax_rate_country, WC_EU_VAT_Number::get_eu_countries(), true ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to look for Greece (GR) code and
|
||||
* convert it to (EL) as that is the standard
|
||||
* country code when in VAT context. This is needed
|
||||
* because WC core uses (GR) as the country code.
|
||||
*/
|
||||
$tax_rate_country = 'GR' === $rate->tax_rate_country ? 'EL' : $rate->tax_rate_country;
|
||||
|
||||
/**
|
||||
* Filters tax rate for the reports
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $rate->tax_rate Tax Rate.
|
||||
* @param int $rate_id Rate Id.
|
||||
* @param object $tax_row Tax Row.
|
||||
*/
|
||||
$tax_rate = apply_filters( 'woocommerce_reports_taxes_rate', $rate->tax_rate, $rate_id, $tax_row );
|
||||
// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
?>
|
||||
<tr>
|
||||
<th scope="row"><?php echo esc_html( WC()->countries->countries[ $rate->tax_rate_country ] ); ?></th>
|
||||
<th scope="row"><?php echo esc_html( $tax_rate_country ); ?></th>
|
||||
<td><?php echo wp_kses_post( $tax_rate ); ?>%</td>
|
||||
<td class="total_row"><?php echo wc_price( $tax_row->amount ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $tax_row->refunded_amount * -1 ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $tax_row->amount + $tax_row->refunded_amount ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $tax_row->tax_amount ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $tax_row->refunded_tax_amount * -1 ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $tax_row->tax_amount + $tax_row->refunded_tax_amount ); ?></td>
|
||||
</tr>
|
||||
<?php
|
||||
// phpcs:enable
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
<?php else : ?>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><?php esc_html_e( 'No taxes found in this period', 'woocommerce-eu-vat-number' ); ?></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<?php endif; ?>
|
||||
</table>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
<?php
|
||||
/**
|
||||
* EU VAT Report
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
* @phpcs:disable WordPress.DateTime.RestrictedFunctions.date_date
|
||||
* @phpcs:disable WordPress.DateTime.CurrentTimeTimestamp.Requested
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_EU_VAT_Report_B2C_Sales class
|
||||
*/
|
||||
class WC_EU_VAT_Report_EU_VAT extends WC_Admin_Report {
|
||||
|
||||
/**
|
||||
* Get the legend for the main chart sidebar.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_chart_legend() {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Output an export link
|
||||
*/
|
||||
public function get_export_button() {
|
||||
$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : 'last_month'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
?>
|
||||
<a
|
||||
href="#"
|
||||
download="report-<?php echo esc_attr( $current_range ); ?>-<?php echo esc_attr( date_i18n( 'Y-m-d', current_time( 'timestamp' ) ) ); ?>.csv"
|
||||
class="export_csv"
|
||||
data-export="table"
|
||||
>
|
||||
<?php esc_html_e( 'Export CSV', 'woocommerce-eu-vat-number' ); ?>
|
||||
</a>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the report
|
||||
*/
|
||||
public function output_report() {
|
||||
$ranges = array(
|
||||
'prev_quarter' => __( 'Previous Quarter', 'woocommerce-eu-vat-number' ),
|
||||
'last_quarter' => __( 'Last Quarter', 'woocommerce-eu-vat-number' ),
|
||||
'quarter' => __( 'This Quarter', 'woocommerce-eu-vat-number' ),
|
||||
);
|
||||
|
||||
$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : 'quarter'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
|
||||
if ( ! in_array( $current_range, array( 'custom', 'prev_quarter', 'last_quarter', 'quarter' ), true ) ) {
|
||||
$current_range = 'quarter';
|
||||
}
|
||||
|
||||
$this->calculate_current_range( $current_range );
|
||||
|
||||
$hide_sidebar = true;
|
||||
|
||||
include WC()->plugin_path() . '/includes/admin/views/html-report-by-date.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current range and calculate the start and end dates
|
||||
*
|
||||
* @param string $current_range Report Range.
|
||||
*/
|
||||
public function calculate_current_range( $current_range ) {
|
||||
$this->chart_groupby = 'month';
|
||||
$quarter = absint( ceil( date( 'm', current_time( 'timestamp' ) ) / 3 ) );
|
||||
$year = absint( date( 'Y', current_time( 'timestamp' ) ) );
|
||||
|
||||
switch ( $current_range ) {
|
||||
case 'prev_quarter':
|
||||
$quarter = $quarter - 2;
|
||||
if ( 0 === $quarter ) {
|
||||
$quarter = 4;
|
||||
$year --;
|
||||
} elseif ( -1 === $quarter ) {
|
||||
$quarter = 3;
|
||||
$year --;
|
||||
}
|
||||
break;
|
||||
case 'last_quarter':
|
||||
--$quarter;
|
||||
if ( 0 === $quarter ) {
|
||||
$quarter = 4;
|
||||
$year --;
|
||||
}
|
||||
break;
|
||||
case 'custom':
|
||||
parent::calculate_current_range( $current_range );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 1 === $quarter ) {
|
||||
$this->start_date = strtotime( $year . '-01-01' );
|
||||
$this->end_date = strtotime( date( 'Y-m-t', strtotime( $year . '-03-01' ) ) );
|
||||
} elseif ( 2 === $quarter ) {
|
||||
$this->start_date = strtotime( $year . '-04-01' );
|
||||
$this->end_date = strtotime( date( 'Y-m-t', strtotime( $year . '-06-01' ) ) );
|
||||
} elseif ( 3 === $quarter ) {
|
||||
$this->start_date = strtotime( $year . '-07-01' );
|
||||
$this->end_date = strtotime( date( 'Y-m-t', strtotime( $year . '-09-01' ) ) );
|
||||
} elseif ( 4 === $quarter ) {
|
||||
$this->start_date = strtotime( $year . '-10-01' );
|
||||
$this->end_date = strtotime( date( 'Y-m-t', strtotime( $year . '-12-01' ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the main chart
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function get_main_chart() {
|
||||
global $wpdb;
|
||||
|
||||
$debug = false;
|
||||
|
||||
// If debug is enabled, don't use cached data.
|
||||
if ( defined( 'WP_DEBUG' ) && WP_DEBUG ) {
|
||||
$debug = true;
|
||||
}
|
||||
|
||||
$line_data = $this->get_order_report_data(
|
||||
array(
|
||||
'data' => array(
|
||||
'_line_total' => array(
|
||||
'type' => 'order_item_meta',
|
||||
'order_item_type' => '',
|
||||
'function' => '',
|
||||
'name' => '_line_total',
|
||||
),
|
||||
'_line_tax_data' => array(
|
||||
'type' => 'order_item_meta',
|
||||
'order_item_type' => '',
|
||||
'function' => '',
|
||||
'name' => '_line_tax_data',
|
||||
),
|
||||
'ID' => array(
|
||||
'type' => 'post_data',
|
||||
'function' => '',
|
||||
'name' => 'refund_id',
|
||||
),
|
||||
),
|
||||
'filter_range' => true,
|
||||
'query_type' => 'get_results',
|
||||
'group_by' => '',
|
||||
'order_types' => array( 'shop_order', 'shop_order_refund' ),
|
||||
'order_status' => array( 'completed', 'refunded' ),
|
||||
'nocache' => $debug,
|
||||
)
|
||||
);
|
||||
|
||||
$grouped_tax_rows = array();
|
||||
|
||||
foreach ( $line_data as $data ) {
|
||||
$line_total = $data->_line_total;
|
||||
$line_tax_data = maybe_unserialize( $data->_line_tax_data );
|
||||
|
||||
foreach ( $line_tax_data['total'] as $tax_id => $tax_value ) {
|
||||
if ( ! isset( $grouped_tax_rows[ $tax_id ] ) ) {
|
||||
$grouped_tax_rows[ $tax_id ] = (object) array(
|
||||
'amount' => 0,
|
||||
'refunded_amount' => 0,
|
||||
'tax_amount' => 0,
|
||||
'refunded_tax_amount' => 0,
|
||||
);
|
||||
}
|
||||
|
||||
if ( $line_total < 0 ) {
|
||||
$grouped_tax_rows[ $tax_id ]->refunded_amount += $line_total;
|
||||
} else {
|
||||
$grouped_tax_rows[ $tax_id ]->amount += $line_total;
|
||||
}
|
||||
|
||||
if ( $tax_value < 0 ) {
|
||||
$grouped_tax_rows[ $tax_id ]->refunded_tax_amount += wc_round_tax_total( $tax_value );
|
||||
} else {
|
||||
$grouped_tax_rows[ $tax_id ]->tax_amount += wc_round_tax_total( $tax_value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$refunded_line_data = $this->get_order_report_data(
|
||||
array(
|
||||
'data' => array(
|
||||
'_line_total' => array(
|
||||
'type' => 'order_item_meta',
|
||||
'order_item_type' => '',
|
||||
'function' => '',
|
||||
'name' => '_line_total',
|
||||
),
|
||||
'_line_tax_data' => array(
|
||||
'type' => 'order_item_meta',
|
||||
'order_item_type' => '',
|
||||
'function' => '',
|
||||
'name' => '_line_tax_data',
|
||||
),
|
||||
),
|
||||
'filter_range' => true,
|
||||
'query_type' => 'get_results',
|
||||
'group_by' => '',
|
||||
'order_types' => array( 'shop_order', 'shop_order_refund' ),
|
||||
'order_status' => array( 'refunded' ),
|
||||
'nocache' => $debug,
|
||||
)
|
||||
);
|
||||
|
||||
foreach ( $refunded_line_data as $data ) {
|
||||
$line_total = $data->_line_total;
|
||||
$line_tax_data = maybe_unserialize( $data->_line_tax_data );
|
||||
|
||||
foreach ( $line_tax_data['total'] as $tax_id => $tax_value ) {
|
||||
if ( ! isset( $grouped_tax_rows[ $tax_id ] ) ) {
|
||||
$grouped_tax_rows[ $tax_id ] = (object) array(
|
||||
'amount' => 0,
|
||||
'refunded_amount' => 0,
|
||||
'tax_amount' => 0,
|
||||
'refunded_tax_amount' => 0,
|
||||
);
|
||||
}
|
||||
|
||||
$grouped_tax_rows[ $tax_id ]->refunded_amount += ( $line_total * -1 );
|
||||
$grouped_tax_rows[ $tax_id ]->refunded_tax_amount += wc_round_tax_total( (float) $tax_value * -1 );
|
||||
}
|
||||
}
|
||||
|
||||
$shipping_tax_amount = $this->get_order_report_data(
|
||||
array(
|
||||
'data' => array(
|
||||
'rate_id' => array(
|
||||
'type' => 'order_item_meta',
|
||||
'order_item_type' => '',
|
||||
'function' => '',
|
||||
'name' => 'rate_id',
|
||||
),
|
||||
'shipping_tax_amount' => array(
|
||||
'type' => 'order_item_meta',
|
||||
'order_item_type' => 'tax',
|
||||
'function' => '',
|
||||
'name' => 'shipping_tax_amount',
|
||||
),
|
||||
),
|
||||
'filter_range' => true,
|
||||
'query_type' => 'get_results',
|
||||
'group_by' => '',
|
||||
'order_types' => array( 'shop_order', 'shop_order_refund' ),
|
||||
'order_status' => array( 'completed' ),
|
||||
'nocache' => $debug,
|
||||
)
|
||||
);
|
||||
|
||||
foreach ( $shipping_tax_amount as $data ) {
|
||||
$tax_value = $data->shipping_tax_amount;
|
||||
$tax_id = $data->rate_id;
|
||||
|
||||
if ( ! isset( $grouped_tax_rows[ $tax_id ] ) ) {
|
||||
$grouped_tax_rows[ $tax_id ] = (object) array(
|
||||
'amount' => 0,
|
||||
'refunded_amount' => 0,
|
||||
'tax_amount' => 0,
|
||||
'refunded_tax_amount' => 0,
|
||||
);
|
||||
}
|
||||
|
||||
$grouped_tax_rows[ $tax_id ]->tax_amount += wc_round_tax_total( $tax_value );
|
||||
}
|
||||
|
||||
$refund_amounts = $this->get_order_report_data(
|
||||
array(
|
||||
'data' => array(
|
||||
'ID' => array(
|
||||
'type' => 'post_data',
|
||||
'function' => '',
|
||||
'name' => 'refund_id',
|
||||
),
|
||||
'post_parent' => array(
|
||||
'type' => 'post_data',
|
||||
'function' => '',
|
||||
'name' => 'order_id',
|
||||
),
|
||||
'_refund_amount' => array(
|
||||
'type' => 'meta',
|
||||
'function' => '',
|
||||
'name' => 'total_refund',
|
||||
),
|
||||
),
|
||||
'group_by' => 'refund_id',
|
||||
'query_type' => 'get_results',
|
||||
'filter_range' => true,
|
||||
'order_status' => false,
|
||||
'parent_order_status' => array( 'completed', 'processing', 'on-hold' ),
|
||||
'nocache' => $debug,
|
||||
)
|
||||
);
|
||||
|
||||
foreach ( $refund_amounts as $refund_data ) {
|
||||
$order = wc_get_order( $refund_data->order_id );
|
||||
|
||||
if ( is_object( $order ) ) {
|
||||
$cached_results = get_transient( strtolower( get_class( $this ) . '_' . $refund_data->order_id ) );
|
||||
|
||||
if ( false === $cached_results ) {
|
||||
$cached_results = $wpdb->get_var( $wpdb->prepare( "SELECT meta_value FROM {$wpdb->prefix}woocommerce_order_itemmeta AS order_itemmeta LEFT JOIN {$wpdb->prefix}woocommerce_order_items AS order_items ON order_itemmeta.order_item_id = order_items.order_item_id WHERE order_items.order_id = %d AND order_items.order_item_type = %s AND order_itemmeta.meta_key = %s", $refund_data->order_id, 'tax', 'rate_id' ) );
|
||||
|
||||
set_transient( strtolower( get_class( $this ) . '_' . $refund_data->order_id ), $cached_results, DAY_IN_SECONDS );
|
||||
}
|
||||
|
||||
$tax_id = $cached_results;
|
||||
|
||||
if ( isset( $grouped_tax_rows[ $tax_id ] ) ) {
|
||||
|
||||
$total_refund = $refund_data->total_refund;
|
||||
|
||||
// Subtract any line items from this total.
|
||||
foreach ( $line_data as $data ) {
|
||||
if ( $refund_data->refund_id === $data->refund_id ) {
|
||||
$total_refund += $data->_line_total;
|
||||
$line_tax_data = maybe_unserialize( $data->_line_tax_data );
|
||||
|
||||
foreach ( $line_tax_data['total'] as $tax_id => $tax_value ) {
|
||||
$total_refund += wc_round_tax_total( $tax_value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$grouped_tax_rows[ $tax_id ]->refunded_amount += -$total_refund;
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
||||
<table class="widefat">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?php esc_html_e( 'Country', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th><?php esc_html_e( 'Code', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th><?php esc_html_e( 'Tax Rate', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th class="total_row"><?php esc_html_e( 'Amount', 'woocommerce-eu-vat-number-eu-vat' ); ?></th>
|
||||
<th class="total_row"><?php esc_html_e( 'Refunded Amount', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th class="total_row"><?php esc_html_e( 'Final Amount', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th class="total_row"><?php esc_html_e( 'Tax Amount', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th class="total_row"><?php esc_html_e( 'Tax Refunded Amount', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th class="total_row"><?php esc_html_e( 'Final Tax Amount ', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<?php if ( $grouped_tax_rows ) : ?>
|
||||
<tbody>
|
||||
<?php
|
||||
foreach ( $grouped_tax_rows as $rate_id => $tax_row ) {
|
||||
$rate = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_id = %d;", $rate_id ) );
|
||||
|
||||
if ( ! is_object( $rate ) || ! in_array( $rate->tax_rate_country, WC_EU_VAT_Number::get_eu_countries(), true ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* We need to look for Greece (GR) code and
|
||||
* convert it to (EL) as that is the standard
|
||||
* country code when in VAT context. This is needed
|
||||
* because WC core uses (GR) as the country code.
|
||||
*/
|
||||
$tax_rate_country = 'GR' === $rate->tax_rate_country ? 'EL' : $rate->tax_rate_country;
|
||||
|
||||
/**
|
||||
* Filters tax rate for the reports
|
||||
*
|
||||
* @since 2.0.0
|
||||
*
|
||||
* @param string $rate->tax_rate Tax Rate.
|
||||
* @param int $rate_id Rate Id.
|
||||
* @param object $tax_row Tax Row.
|
||||
*/
|
||||
$tax_rate = apply_filters( 'woocommerce_reports_taxes_rate', $rate->tax_rate, $rate_id, $tax_row );
|
||||
// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
?>
|
||||
<tr>
|
||||
<th scope="row"><?php echo esc_html( WC()->countries->countries[ $rate->tax_rate_country ] ); ?></th>
|
||||
<th scope="row"><?php echo esc_html( $tax_rate_country ); ?></th>
|
||||
<td><?php echo wp_kses_post( $tax_rate ); ?>%</td>
|
||||
<td class="total_row"><?php echo wc_price( $tax_row->amount ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $tax_row->refunded_amount * -1 ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $tax_row->amount + $tax_row->refunded_amount ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $tax_row->tax_amount ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $tax_row->refunded_tax_amount * -1 ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $tax_row->tax_amount + $tax_row->refunded_tax_amount ); ?></td>
|
||||
</tr>
|
||||
<?php
|
||||
// phpcs:enable
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
<?php else : ?>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><?php esc_html_e( 'No taxes found in this period', 'woocommerce-eu-vat-number' ); ?></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<?php endif; ?>
|
||||
</table>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,82 +1,82 @@
|
|||
<?php
|
||||
/**
|
||||
* EU VAT Reports
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_EU_VAT_Reports class
|
||||
*/
|
||||
class WC_EU_VAT_Reports {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public static function init() {
|
||||
add_action( 'woocommerce_admin_reports', array( __CLASS__, 'init_reports' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add reports
|
||||
*
|
||||
* @param array $reports EU VAT reports.
|
||||
* @return array
|
||||
*/
|
||||
public static function init_reports( $reports ) {
|
||||
if ( isset( $reports['taxes'] ) ) {
|
||||
$reports['taxes']['reports']['ec_sales_list'] = array(
|
||||
'title' => __( 'EC Sales List', 'woocommerce-eu-vat-number' ),
|
||||
'description' => '',
|
||||
'hide_title' => true,
|
||||
'callback' => array( __CLASS__, 'ec_sales_list' ),
|
||||
);
|
||||
$reports['taxes']['reports']['eu_vat'] = array(
|
||||
'title' => __( 'EU VAT by state', 'woocommerce-eu-vat-number' ),
|
||||
'description' => '',
|
||||
'hide_title' => true,
|
||||
'callback' => array( __CLASS__, 'eu_vat' ),
|
||||
);
|
||||
$reports['taxes']['reports']['non_eu_vat'] = array(
|
||||
'title' => __( 'Non EU Sales', 'woocommerce-eu-vat-number' ),
|
||||
'description' => '',
|
||||
'hide_title' => true,
|
||||
'callback' => array( __CLASS__, 'non_eu_vat' ),
|
||||
);
|
||||
}
|
||||
return $reports;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a report
|
||||
*/
|
||||
public static function ec_sales_list() {
|
||||
include_once 'class-wc-eu-vat-report-ec-sales-list.php';
|
||||
$report = new WC_EU_VAT_Report_EC_Sales_List();
|
||||
$report->output_report();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a report
|
||||
*/
|
||||
public static function eu_vat() {
|
||||
include_once 'class-wc-eu-vat-report-eu-vat.php';
|
||||
$report = new WC_EU_VAT_Report_EU_VAT();
|
||||
$report->output_report();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a report
|
||||
*/
|
||||
public static function non_eu_vat() {
|
||||
include_once 'class-wc-non-eu-sales-report.php';
|
||||
$report = new WC_Non_EU_Sales_Report();
|
||||
$report->output_report();
|
||||
}
|
||||
}
|
||||
|
||||
WC_EU_VAT_Reports::init();
|
||||
<?php
|
||||
/**
|
||||
* EU VAT Reports
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_EU_VAT_Reports class
|
||||
*/
|
||||
class WC_EU_VAT_Reports {
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public static function init() {
|
||||
add_action( 'woocommerce_admin_reports', array( __CLASS__, 'init_reports' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add reports
|
||||
*
|
||||
* @param array $reports EU VAT reports.
|
||||
* @return array
|
||||
*/
|
||||
public static function init_reports( $reports ) {
|
||||
if ( isset( $reports['taxes'] ) ) {
|
||||
$reports['taxes']['reports']['ec_sales_list'] = array(
|
||||
'title' => __( 'EC Sales List', 'woocommerce-eu-vat-number' ),
|
||||
'description' => '',
|
||||
'hide_title' => true,
|
||||
'callback' => array( __CLASS__, 'ec_sales_list' ),
|
||||
);
|
||||
$reports['taxes']['reports']['eu_vat'] = array(
|
||||
'title' => __( 'EU VAT by state', 'woocommerce-eu-vat-number' ),
|
||||
'description' => '',
|
||||
'hide_title' => true,
|
||||
'callback' => array( __CLASS__, 'eu_vat' ),
|
||||
);
|
||||
$reports['taxes']['reports']['non_eu_vat'] = array(
|
||||
'title' => __( 'Non EU Sales', 'woocommerce-eu-vat-number' ),
|
||||
'description' => '',
|
||||
'hide_title' => true,
|
||||
'callback' => array( __CLASS__, 'non_eu_vat' ),
|
||||
);
|
||||
}
|
||||
return $reports;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a report
|
||||
*/
|
||||
public static function ec_sales_list() {
|
||||
include_once 'class-wc-eu-vat-report-ec-sales-list.php';
|
||||
$report = new WC_EU_VAT_Report_EC_Sales_List();
|
||||
$report->output_report();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a report
|
||||
*/
|
||||
public static function eu_vat() {
|
||||
include_once 'class-wc-eu-vat-report-eu-vat.php';
|
||||
$report = new WC_EU_VAT_Report_EU_VAT();
|
||||
$report->output_report();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a report
|
||||
*/
|
||||
public static function non_eu_vat() {
|
||||
include_once 'class-wc-non-eu-sales-report.php';
|
||||
$report = new WC_Non_EU_Sales_Report();
|
||||
$report->output_report();
|
||||
}
|
||||
}
|
||||
|
||||
WC_EU_VAT_Reports::init();
|
||||
|
|
|
@ -1,70 +1,70 @@
|
|||
<?php
|
||||
/**
|
||||
* UK VAT Number API class
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_EU_VAT_UK_Number_API class.
|
||||
*/
|
||||
class WC_EU_VAT_UK_Number_API {
|
||||
|
||||
/**
|
||||
* UK VAT Number API URL.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $api_url = 'https://api.service.hmrc.gov.uk/organisations/vat/check-vat-number/lookup/';
|
||||
|
||||
/**
|
||||
* UK VAT Number API Version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $api_version = '1.0';
|
||||
|
||||
|
||||
/**
|
||||
* Check VAT Number
|
||||
*
|
||||
* @param string $vat_number UK VAT Number to be validate.
|
||||
*
|
||||
* @return array|WP_Error A WordPress HTTP response.
|
||||
* @throws Exception When remote request fails.
|
||||
*/
|
||||
public function check_vat_number( $vat_number ) {
|
||||
if ( empty( $vat_number ) ) {
|
||||
return false;
|
||||
}
|
||||
$api_url = $this->api_url . $vat_number;
|
||||
$response = wp_remote_get(
|
||||
esc_url_raw( $api_url ),
|
||||
array(
|
||||
'timeout' => 30,
|
||||
'headers' => array(
|
||||
'Accept' => "application/vnd.hmrc.{$this->api_version}+json",
|
||||
),
|
||||
'user-agent' => 'WooCommerce/' . WC()->version,
|
||||
)
|
||||
);
|
||||
|
||||
if ( is_wp_error( $response ) ) {
|
||||
throw new Exception( $response->get_error_message() );
|
||||
}
|
||||
|
||||
// Check if VAT number is valid.
|
||||
$response_code = wp_remote_retrieve_response_code( $response );
|
||||
if ( 200 === $response_code ) {
|
||||
$results = json_decode( wp_remote_retrieve_body( $response ), true );
|
||||
if ( isset( $results['target'] ) && isset( $results['target']['vatNumber'] ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
<?php
|
||||
/**
|
||||
* UK VAT Number API class
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_EU_VAT_UK_Number_API class.
|
||||
*/
|
||||
class WC_EU_VAT_UK_Number_API {
|
||||
|
||||
/**
|
||||
* UK VAT Number API URL.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $api_url = 'https://api.service.hmrc.gov.uk/organisations/vat/check-vat-number/lookup/';
|
||||
|
||||
/**
|
||||
* UK VAT Number API Version.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $api_version = '1.0';
|
||||
|
||||
|
||||
/**
|
||||
* Check VAT Number
|
||||
*
|
||||
* @param string $vat_number UK VAT Number to be validate.
|
||||
*
|
||||
* @return array|WP_Error A WordPress HTTP response.
|
||||
* @throws Exception When remote request fails.
|
||||
*/
|
||||
public function check_vat_number( $vat_number ) {
|
||||
if ( empty( $vat_number ) ) {
|
||||
return false;
|
||||
}
|
||||
$api_url = $this->api_url . $vat_number;
|
||||
$response = wp_remote_get(
|
||||
esc_url_raw( $api_url ),
|
||||
array(
|
||||
'timeout' => 30,
|
||||
'headers' => array(
|
||||
'Accept' => "application/vnd.hmrc.{$this->api_version}+json",
|
||||
),
|
||||
'user-agent' => 'WooCommerce/' . WC()->version,
|
||||
)
|
||||
);
|
||||
|
||||
if ( is_wp_error( $response ) ) {
|
||||
throw new Exception( $response->get_error_message() );
|
||||
}
|
||||
|
||||
// Check if VAT number is valid.
|
||||
$response_code = wp_remote_retrieve_response_code( $response );
|
||||
if ( 200 === $response_code ) {
|
||||
$results = json_decode( wp_remote_retrieve_body( $response ), true );
|
||||
if ( isset( $results['target'] ) && isset( $results['target']['vatNumber'] ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,409 +1,409 @@
|
|||
<?php
|
||||
/**
|
||||
* EU VAT Sales Report
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
* @phpcs:disable WordPress.DateTime.RestrictedFunctions.date_date
|
||||
* @phpcs:disable WordPress.DateTime.CurrentTimeTimestamp.Requested
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_Non_EU_Sales_Report class
|
||||
*/
|
||||
class WC_Non_EU_Sales_Report extends WC_Admin_Report {
|
||||
|
||||
/**
|
||||
* Get the legend for the main chart sidebar
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_chart_legend() {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Output an export link
|
||||
*/
|
||||
public function get_export_button() {
|
||||
$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : 'last_month'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
|
||||
?><a href="#" download="report-<?php echo esc_attr( $current_range ); ?>-<?php echo esc_attr( date_i18n( 'Y-m-d', current_time( 'timestamp' ) ) ); ?>.csv" class="export_csv" data-export="table">
|
||||
<?php esc_html_e( 'Export CSV', 'woocommerce-eu-vat-number' ); ?>
|
||||
</a>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the report
|
||||
*/
|
||||
public function output_report() {
|
||||
$ranges = array(
|
||||
'prev_quarter' => __( 'Previous Quarter', 'woocommerce-eu-vat-number' ),
|
||||
'last_quarter' => __( 'Last Quarter', 'woocommerce-eu-vat-number' ),
|
||||
'quarter' => __( 'This Quarter', 'woocommerce-eu-vat-number' ),
|
||||
);
|
||||
|
||||
$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : 'quarter'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
|
||||
if ( ! in_array( $current_range, array( 'custom', 'prev_quarter', 'last_quarter', 'quarter' ), true ) ) {
|
||||
$current_range = 'quarter';
|
||||
}
|
||||
|
||||
$this->calculate_current_range( $current_range );
|
||||
|
||||
$hide_sidebar = true;
|
||||
|
||||
include WC()->plugin_path() . '/includes/admin/views/html-report-by-date.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current range and calculate the start and end dates
|
||||
*
|
||||
* @param string $current_range Report Range.
|
||||
*/
|
||||
public function calculate_current_range( $current_range ) {
|
||||
$this->chart_groupby = 'month';
|
||||
$quarter = absint( ceil( date( 'm', current_time( 'timestamp' ) ) / 3 ) );
|
||||
$year = absint( date( 'Y', current_time( 'timestamp' ) ) );
|
||||
|
||||
switch ( $current_range ) {
|
||||
case 'prev_quarter':
|
||||
$quarter = $quarter - 2;
|
||||
if ( 0 === $quarter ) {
|
||||
$quarter = 4;
|
||||
$year --;
|
||||
} elseif ( -1 === $quarter ) {
|
||||
$quarter = 3;
|
||||
$year --;
|
||||
}
|
||||
break;
|
||||
case 'last_quarter':
|
||||
--$quarter;
|
||||
if ( 0 === $quarter ) {
|
||||
$quarter = 4;
|
||||
$year --;
|
||||
}
|
||||
break;
|
||||
case 'custom':
|
||||
parent::calculate_current_range( $current_range );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 1 === $quarter ) {
|
||||
$this->start_date = strtotime( $year . '-01-01' );
|
||||
$this->end_date = strtotime( date( 'Y-m-t', strtotime( $year . '-03-01' ) ) );
|
||||
} elseif ( 2 === $quarter ) {
|
||||
$this->start_date = strtotime( $year . '-04-01' );
|
||||
$this->end_date = strtotime( date( 'Y-m-t', strtotime( $year . '-06-01' ) ) );
|
||||
} elseif ( 3 === $quarter ) {
|
||||
$this->start_date = strtotime( $year . '-07-01' );
|
||||
$this->end_date = strtotime( date( 'Y-m-t', strtotime( $year . '-09-01' ) ) );
|
||||
} elseif ( 4 === $quarter ) {
|
||||
$this->start_date = strtotime( $year . '-10-01' );
|
||||
$this->end_date = strtotime( date( 'Y-m-t', strtotime( $year . '-12-01' ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the main chart
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function get_main_chart() {
|
||||
global $wpdb;
|
||||
|
||||
$line_data = $this->get_order_report_data(
|
||||
array(
|
||||
'data' => array(
|
||||
'_line_total' => array(
|
||||
'type' => 'order_item_meta',
|
||||
'order_item_type' => '',
|
||||
'function' => '',
|
||||
'name' => '_line_total',
|
||||
),
|
||||
'_line_tax_data' => array(
|
||||
'type' => 'order_item_meta',
|
||||
'order_item_type' => '',
|
||||
'function' => '',
|
||||
'name' => '_line_tax_data',
|
||||
),
|
||||
'ID' => array(
|
||||
'type' => 'post_data',
|
||||
'function' => '',
|
||||
'name' => 'ID',
|
||||
),
|
||||
),
|
||||
'filter_range' => true,
|
||||
'query_type' => 'get_results',
|
||||
'group_by' => '',
|
||||
'order_types' => array( 'shop_order', 'shop_order_refund' ),
|
||||
'order_status' => array( 'completed' ),
|
||||
)
|
||||
);
|
||||
|
||||
$grouped_tax_rows = array();
|
||||
|
||||
foreach ( $line_data as $data ) {
|
||||
$line_total = $data->_line_total;
|
||||
$line_tax_data = maybe_unserialize( $data->_line_tax_data );
|
||||
|
||||
if ( $line_tax_data['total'] ) {
|
||||
foreach ( $line_tax_data['total'] as $tax_id => $tax_value ) {
|
||||
if ( ! isset( $grouped_tax_rows[ $tax_id ] ) ) {
|
||||
$grouped_tax_rows[ $tax_id ] = (object) array(
|
||||
'amount' => 0,
|
||||
'refunded_amount' => 0,
|
||||
'tax_amount' => 0,
|
||||
'refunded_tax_amount' => 0,
|
||||
);
|
||||
}
|
||||
|
||||
if ( $line_total < 0 ) {
|
||||
$grouped_tax_rows[ $tax_id ]->refunded_amount += $line_total;
|
||||
} else {
|
||||
$grouped_tax_rows[ $tax_id ]->amount += $line_total;
|
||||
}
|
||||
|
||||
if ( $tax_value < 0 ) {
|
||||
$grouped_tax_rows[ $tax_id ]->refunded_tax_amount += wc_round_tax_total( $tax_value );
|
||||
} else {
|
||||
$grouped_tax_rows[ $tax_id ]->tax_amount += wc_round_tax_total( $tax_value );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$order = wc_get_order( $data->ID );
|
||||
$country = $order->get_meta( '_billing_country', true );
|
||||
|
||||
if ( $country ) {
|
||||
if ( ! isset( $grouped_tax_rows[ $country ] ) ) {
|
||||
$grouped_tax_rows[ $country ] = (object) array(
|
||||
'amount' => 0,
|
||||
'refunded_amount' => 0,
|
||||
'tax_amount' => 0,
|
||||
'refunded_tax_amount' => 0,
|
||||
);
|
||||
}
|
||||
|
||||
if ( $line_total < 0 ) {
|
||||
$grouped_tax_rows[ $country ]->refunded_amount += $line_total;
|
||||
} else {
|
||||
$grouped_tax_rows[ $country ]->amount += $line_total;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$refunded_line_data = $this->get_order_report_data(
|
||||
array(
|
||||
'data' => array(
|
||||
'_line_total' => array(
|
||||
'type' => 'order_item_meta',
|
||||
'order_item_type' => '',
|
||||
'function' => '',
|
||||
'name' => '_line_total',
|
||||
),
|
||||
'_line_tax_data' => array(
|
||||
'type' => 'order_item_meta',
|
||||
'order_item_type' => '',
|
||||
'function' => '',
|
||||
'name' => '_line_tax_data',
|
||||
),
|
||||
'ID' => array(
|
||||
'type' => 'post_data',
|
||||
'function' => '',
|
||||
'name' => 'ID',
|
||||
),
|
||||
),
|
||||
'filter_range' => true,
|
||||
'query_type' => 'get_results',
|
||||
'group_by' => '',
|
||||
'order_types' => array( 'shop_order', 'shop_order_refund' ),
|
||||
'order_status' => array( 'refunded' ),
|
||||
)
|
||||
);
|
||||
|
||||
foreach ( $refunded_line_data as $data ) {
|
||||
$line_total = $data->_line_total;
|
||||
$line_tax_data = maybe_unserialize( $data->_line_tax_data );
|
||||
|
||||
if ( $line_tax_data['total'] ) {
|
||||
foreach ( $line_tax_data['total'] as $tax_id => $tax_value ) {
|
||||
if ( ! isset( $grouped_tax_rows[ $tax_id ] ) ) {
|
||||
$grouped_tax_rows[ $tax_id ] = (object) array(
|
||||
'amount' => 0,
|
||||
'refunded_amount' => 0,
|
||||
'tax_amount' => 0,
|
||||
'refunded_tax_amount' => 0,
|
||||
);
|
||||
}
|
||||
$grouped_tax_rows[ $tax_id ]->refunded_amount += ( $line_total * -1 );
|
||||
$grouped_tax_rows[ $tax_id ]->refunded_tax_amount += ( wc_round_tax_total( $tax_value ) * -1 );
|
||||
}
|
||||
} else {
|
||||
$order = wc_get_order( $data->ID );
|
||||
$country = $order->get_meta( '_billing_country', true );
|
||||
|
||||
if ( $country ) {
|
||||
if ( ! isset( $grouped_tax_rows[ $country ] ) ) {
|
||||
$grouped_tax_rows[ $country ] = (object) array(
|
||||
'amount' => 0,
|
||||
'refunded_amount' => 0,
|
||||
'tax_amount' => 0,
|
||||
'refunded_tax_amount' => 0,
|
||||
);
|
||||
}
|
||||
$grouped_tax_rows[ $country ]->refunded_amount += ( $line_total * -1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$shipping_tax_amount = $this->get_order_report_data(
|
||||
array(
|
||||
'data' => array(
|
||||
'rate_id' => array(
|
||||
'type' => 'order_item_meta',
|
||||
'order_item_type' => '',
|
||||
'function' => '',
|
||||
'name' => 'rate_id',
|
||||
),
|
||||
'shipping_tax_amount' => array(
|
||||
'type' => 'order_item_meta',
|
||||
'order_item_type' => 'tax',
|
||||
'function' => '',
|
||||
'name' => 'shipping_tax_amount',
|
||||
),
|
||||
),
|
||||
'filter_range' => true,
|
||||
'query_type' => 'get_results',
|
||||
'group_by' => '',
|
||||
'order_types' => array( 'shop_order', 'shop_order_refund' ),
|
||||
'order_status' => array( 'completed' ),
|
||||
)
|
||||
);
|
||||
|
||||
foreach ( $shipping_tax_amount as $data ) {
|
||||
$tax_value = $data->shipping_tax_amount;
|
||||
$tax_id = $data->rate_id;
|
||||
|
||||
if ( ! isset( $grouped_tax_rows[ $tax_id ] ) ) {
|
||||
$grouped_tax_rows[ $tax_id ] = (object) array(
|
||||
'amount' => 0,
|
||||
'refunded_amount' => 0,
|
||||
'tax_amount' => 0,
|
||||
'refunded_tax_amount' => 0,
|
||||
);
|
||||
}
|
||||
|
||||
$grouped_tax_rows[ $tax_id ]->tax_amount += wc_round_tax_total( $tax_value );
|
||||
}
|
||||
?>
|
||||
<table class="widefat">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?php esc_html_e( 'Country', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th><?php esc_html_e( 'Code', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th><?php esc_html_e( 'Tax Rate', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th class="total_row"><?php esc_html_e( 'Amount', 'woocommerce-eu-vat-number-eu-vat' ); ?></th>
|
||||
<th class="total_row"><?php esc_html_e( 'Refunded Amount', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th class="total_row"><?php esc_html_e( 'Final Amount', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th class="total_row"><?php esc_html_e( 'Tax Amount', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th class="total_row"><?php esc_html_e( 'Tax Refunded Amount', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th class="total_row"><?php esc_html_e( 'Final Tax Amount ', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$found = false;
|
||||
$total_amount = 0;
|
||||
$total_refunded_amount = 0;
|
||||
$total_final_amount = 0;
|
||||
$total_tax_amount = 0;
|
||||
$total_refunded_tax_amount = 0;
|
||||
$total_final_tax_amount = 0;
|
||||
|
||||
foreach ( $grouped_tax_rows as $rate_id => $tax_row ) {
|
||||
if ( is_numeric( $rate_id ) ) {
|
||||
$rate = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_id = %d;", $rate_id ) );
|
||||
|
||||
if ( ! is_object( $rate ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$country = $rate->tax_rate_country;
|
||||
|
||||
/**
|
||||
* Filters tax rate for the reports
|
||||
*
|
||||
* @since 2.1.7
|
||||
*
|
||||
* @param string $rate->tax_rate Tax Rate.
|
||||
* @param int $rate_id Rate Id.
|
||||
* @param object $tax_row Tax Row.
|
||||
*/
|
||||
$tax_rate = apply_filters( 'woocommerce_reports_taxes_rate', $rate->tax_rate, $rate_id, $tax_row ) . '%';
|
||||
} else {
|
||||
$country = $rate_id;
|
||||
$tax_rate = '-';
|
||||
}
|
||||
|
||||
if ( in_array( $country, WC_EU_VAT_Number::get_eu_countries(), true ) || empty( WC()->countries->countries[ $country ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$found = true;
|
||||
$total_amount += $tax_row->amount;
|
||||
$total_refunded_amount += $tax_row->refunded_amount;
|
||||
$total_final_amount += $tax_row->amount + $tax_row->refunded_amount;
|
||||
$total_tax_amount += $tax_row->tax_amount;
|
||||
$total_refunded_tax_amount += $tax_row->refunded_tax_amount;
|
||||
$total_final_tax_amount += $tax_row->tax_amount + $tax_row->refunded_tax_amount;
|
||||
// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
?>
|
||||
<tr>
|
||||
<th scope="row"><?php echo esc_html( WC()->countries->countries[ $country ] ); ?></th>
|
||||
<th scope="row"><?php echo esc_html( $country ); ?></th>
|
||||
<td><?php echo esc_html( $tax_rate ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $tax_row->amount ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $tax_row->refunded_amount * -1 ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $tax_row->amount + $tax_row->refunded_amount ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $tax_row->tax_amount ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $tax_row->refunded_tax_amount * -1 ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $tax_row->tax_amount + $tax_row->refunded_tax_amount ); ?></td>
|
||||
</tr>
|
||||
<?php
|
||||
// phpcs:enable
|
||||
}
|
||||
|
||||
if ( $found ) {
|
||||
// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
?>
|
||||
<tr>
|
||||
<th><strong><?php esc_html_e( 'Totals', 'woocommerce-eu-vat-number' ); ?></strong></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<td class="total_row"><?php echo wc_price( $total_amount ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $total_refunded_amount * -1 ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $total_final_amount ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $total_tax_amount ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $total_refunded_tax_amount * -1 ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $total_final_tax_amount ); ?></td>
|
||||
</tr>
|
||||
<?php
|
||||
// phpcs:enable
|
||||
} else {
|
||||
?>
|
||||
<tr>
|
||||
<td colspan="9"><?php esc_html_e( 'No non-eu sales found in this period', 'woocommerce-eu-vat-number' ); ?></td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
<?php
|
||||
/**
|
||||
* EU VAT Sales Report
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
* @phpcs:disable WordPress.DateTime.RestrictedFunctions.date_date
|
||||
* @phpcs:disable WordPress.DateTime.CurrentTimeTimestamp.Requested
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* WC_Non_EU_Sales_Report class
|
||||
*/
|
||||
class WC_Non_EU_Sales_Report extends WC_Admin_Report {
|
||||
|
||||
/**
|
||||
* Get the legend for the main chart sidebar
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_chart_legend() {
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Output an export link
|
||||
*/
|
||||
public function get_export_button() {
|
||||
$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : 'last_month'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
|
||||
?><a href="#" download="report-<?php echo esc_attr( $current_range ); ?>-<?php echo esc_attr( date_i18n( 'Y-m-d', current_time( 'timestamp' ) ) ); ?>.csv" class="export_csv" data-export="table">
|
||||
<?php esc_html_e( 'Export CSV', 'woocommerce-eu-vat-number' ); ?>
|
||||
</a>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the report
|
||||
*/
|
||||
public function output_report() {
|
||||
$ranges = array(
|
||||
'prev_quarter' => __( 'Previous Quarter', 'woocommerce-eu-vat-number' ),
|
||||
'last_quarter' => __( 'Last Quarter', 'woocommerce-eu-vat-number' ),
|
||||
'quarter' => __( 'This Quarter', 'woocommerce-eu-vat-number' ),
|
||||
);
|
||||
|
||||
$current_range = ! empty( $_GET['range'] ) ? sanitize_text_field( wp_unslash( $_GET['range'] ) ) : 'quarter'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||
|
||||
if ( ! in_array( $current_range, array( 'custom', 'prev_quarter', 'last_quarter', 'quarter' ), true ) ) {
|
||||
$current_range = 'quarter';
|
||||
}
|
||||
|
||||
$this->calculate_current_range( $current_range );
|
||||
|
||||
$hide_sidebar = true;
|
||||
|
||||
include WC()->plugin_path() . '/includes/admin/views/html-report-by-date.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current range and calculate the start and end dates
|
||||
*
|
||||
* @param string $current_range Report Range.
|
||||
*/
|
||||
public function calculate_current_range( $current_range ) {
|
||||
$this->chart_groupby = 'month';
|
||||
$quarter = absint( ceil( date( 'm', current_time( 'timestamp' ) ) / 3 ) );
|
||||
$year = absint( date( 'Y', current_time( 'timestamp' ) ) );
|
||||
|
||||
switch ( $current_range ) {
|
||||
case 'prev_quarter':
|
||||
$quarter = $quarter - 2;
|
||||
if ( 0 === $quarter ) {
|
||||
$quarter = 4;
|
||||
$year --;
|
||||
} elseif ( -1 === $quarter ) {
|
||||
$quarter = 3;
|
||||
$year --;
|
||||
}
|
||||
break;
|
||||
case 'last_quarter':
|
||||
--$quarter;
|
||||
if ( 0 === $quarter ) {
|
||||
$quarter = 4;
|
||||
$year --;
|
||||
}
|
||||
break;
|
||||
case 'custom':
|
||||
parent::calculate_current_range( $current_range );
|
||||
return;
|
||||
}
|
||||
|
||||
if ( 1 === $quarter ) {
|
||||
$this->start_date = strtotime( $year . '-01-01' );
|
||||
$this->end_date = strtotime( date( 'Y-m-t', strtotime( $year . '-03-01' ) ) );
|
||||
} elseif ( 2 === $quarter ) {
|
||||
$this->start_date = strtotime( $year . '-04-01' );
|
||||
$this->end_date = strtotime( date( 'Y-m-t', strtotime( $year . '-06-01' ) ) );
|
||||
} elseif ( 3 === $quarter ) {
|
||||
$this->start_date = strtotime( $year . '-07-01' );
|
||||
$this->end_date = strtotime( date( 'Y-m-t', strtotime( $year . '-09-01' ) ) );
|
||||
} elseif ( 4 === $quarter ) {
|
||||
$this->start_date = strtotime( $year . '-10-01' );
|
||||
$this->end_date = strtotime( date( 'Y-m-t', strtotime( $year . '-12-01' ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the main chart
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function get_main_chart() {
|
||||
global $wpdb;
|
||||
|
||||
$line_data = $this->get_order_report_data(
|
||||
array(
|
||||
'data' => array(
|
||||
'_line_total' => array(
|
||||
'type' => 'order_item_meta',
|
||||
'order_item_type' => '',
|
||||
'function' => '',
|
||||
'name' => '_line_total',
|
||||
),
|
||||
'_line_tax_data' => array(
|
||||
'type' => 'order_item_meta',
|
||||
'order_item_type' => '',
|
||||
'function' => '',
|
||||
'name' => '_line_tax_data',
|
||||
),
|
||||
'ID' => array(
|
||||
'type' => 'post_data',
|
||||
'function' => '',
|
||||
'name' => 'ID',
|
||||
),
|
||||
),
|
||||
'filter_range' => true,
|
||||
'query_type' => 'get_results',
|
||||
'group_by' => '',
|
||||
'order_types' => array( 'shop_order', 'shop_order_refund' ),
|
||||
'order_status' => array( 'completed' ),
|
||||
)
|
||||
);
|
||||
|
||||
$grouped_tax_rows = array();
|
||||
|
||||
foreach ( $line_data as $data ) {
|
||||
$line_total = $data->_line_total;
|
||||
$line_tax_data = maybe_unserialize( $data->_line_tax_data );
|
||||
|
||||
if ( $line_tax_data['total'] ) {
|
||||
foreach ( $line_tax_data['total'] as $tax_id => $tax_value ) {
|
||||
if ( ! isset( $grouped_tax_rows[ $tax_id ] ) ) {
|
||||
$grouped_tax_rows[ $tax_id ] = (object) array(
|
||||
'amount' => 0,
|
||||
'refunded_amount' => 0,
|
||||
'tax_amount' => 0,
|
||||
'refunded_tax_amount' => 0,
|
||||
);
|
||||
}
|
||||
|
||||
if ( $line_total < 0 ) {
|
||||
$grouped_tax_rows[ $tax_id ]->refunded_amount += $line_total;
|
||||
} else {
|
||||
$grouped_tax_rows[ $tax_id ]->amount += $line_total;
|
||||
}
|
||||
|
||||
if ( $tax_value < 0 ) {
|
||||
$grouped_tax_rows[ $tax_id ]->refunded_tax_amount += wc_round_tax_total( $tax_value );
|
||||
} else {
|
||||
$grouped_tax_rows[ $tax_id ]->tax_amount += wc_round_tax_total( $tax_value );
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$order = wc_get_order( $data->ID );
|
||||
$country = $order->get_meta( '_billing_country', true );
|
||||
|
||||
if ( $country ) {
|
||||
if ( ! isset( $grouped_tax_rows[ $country ] ) ) {
|
||||
$grouped_tax_rows[ $country ] = (object) array(
|
||||
'amount' => 0,
|
||||
'refunded_amount' => 0,
|
||||
'tax_amount' => 0,
|
||||
'refunded_tax_amount' => 0,
|
||||
);
|
||||
}
|
||||
|
||||
if ( $line_total < 0 ) {
|
||||
$grouped_tax_rows[ $country ]->refunded_amount += $line_total;
|
||||
} else {
|
||||
$grouped_tax_rows[ $country ]->amount += $line_total;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$refunded_line_data = $this->get_order_report_data(
|
||||
array(
|
||||
'data' => array(
|
||||
'_line_total' => array(
|
||||
'type' => 'order_item_meta',
|
||||
'order_item_type' => '',
|
||||
'function' => '',
|
||||
'name' => '_line_total',
|
||||
),
|
||||
'_line_tax_data' => array(
|
||||
'type' => 'order_item_meta',
|
||||
'order_item_type' => '',
|
||||
'function' => '',
|
||||
'name' => '_line_tax_data',
|
||||
),
|
||||
'ID' => array(
|
||||
'type' => 'post_data',
|
||||
'function' => '',
|
||||
'name' => 'ID',
|
||||
),
|
||||
),
|
||||
'filter_range' => true,
|
||||
'query_type' => 'get_results',
|
||||
'group_by' => '',
|
||||
'order_types' => array( 'shop_order', 'shop_order_refund' ),
|
||||
'order_status' => array( 'refunded' ),
|
||||
)
|
||||
);
|
||||
|
||||
foreach ( $refunded_line_data as $data ) {
|
||||
$line_total = $data->_line_total;
|
||||
$line_tax_data = maybe_unserialize( $data->_line_tax_data );
|
||||
|
||||
if ( $line_tax_data['total'] ) {
|
||||
foreach ( $line_tax_data['total'] as $tax_id => $tax_value ) {
|
||||
if ( ! isset( $grouped_tax_rows[ $tax_id ] ) ) {
|
||||
$grouped_tax_rows[ $tax_id ] = (object) array(
|
||||
'amount' => 0,
|
||||
'refunded_amount' => 0,
|
||||
'tax_amount' => 0,
|
||||
'refunded_tax_amount' => 0,
|
||||
);
|
||||
}
|
||||
$grouped_tax_rows[ $tax_id ]->refunded_amount += ( $line_total * -1 );
|
||||
$grouped_tax_rows[ $tax_id ]->refunded_tax_amount += ( wc_round_tax_total( $tax_value ) * -1 );
|
||||
}
|
||||
} else {
|
||||
$order = wc_get_order( $data->ID );
|
||||
$country = $order->get_meta( '_billing_country', true );
|
||||
|
||||
if ( $country ) {
|
||||
if ( ! isset( $grouped_tax_rows[ $country ] ) ) {
|
||||
$grouped_tax_rows[ $country ] = (object) array(
|
||||
'amount' => 0,
|
||||
'refunded_amount' => 0,
|
||||
'tax_amount' => 0,
|
||||
'refunded_tax_amount' => 0,
|
||||
);
|
||||
}
|
||||
$grouped_tax_rows[ $country ]->refunded_amount += ( $line_total * -1 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$shipping_tax_amount = $this->get_order_report_data(
|
||||
array(
|
||||
'data' => array(
|
||||
'rate_id' => array(
|
||||
'type' => 'order_item_meta',
|
||||
'order_item_type' => '',
|
||||
'function' => '',
|
||||
'name' => 'rate_id',
|
||||
),
|
||||
'shipping_tax_amount' => array(
|
||||
'type' => 'order_item_meta',
|
||||
'order_item_type' => 'tax',
|
||||
'function' => '',
|
||||
'name' => 'shipping_tax_amount',
|
||||
),
|
||||
),
|
||||
'filter_range' => true,
|
||||
'query_type' => 'get_results',
|
||||
'group_by' => '',
|
||||
'order_types' => array( 'shop_order', 'shop_order_refund' ),
|
||||
'order_status' => array( 'completed' ),
|
||||
)
|
||||
);
|
||||
|
||||
foreach ( $shipping_tax_amount as $data ) {
|
||||
$tax_value = $data->shipping_tax_amount;
|
||||
$tax_id = $data->rate_id;
|
||||
|
||||
if ( ! isset( $grouped_tax_rows[ $tax_id ] ) ) {
|
||||
$grouped_tax_rows[ $tax_id ] = (object) array(
|
||||
'amount' => 0,
|
||||
'refunded_amount' => 0,
|
||||
'tax_amount' => 0,
|
||||
'refunded_tax_amount' => 0,
|
||||
);
|
||||
}
|
||||
|
||||
$grouped_tax_rows[ $tax_id ]->tax_amount += wc_round_tax_total( $tax_value );
|
||||
}
|
||||
?>
|
||||
<table class="widefat">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><?php esc_html_e( 'Country', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th><?php esc_html_e( 'Code', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th><?php esc_html_e( 'Tax Rate', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th class="total_row"><?php esc_html_e( 'Amount', 'woocommerce-eu-vat-number-eu-vat' ); ?></th>
|
||||
<th class="total_row"><?php esc_html_e( 'Refunded Amount', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th class="total_row"><?php esc_html_e( 'Final Amount', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th class="total_row"><?php esc_html_e( 'Tax Amount', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th class="total_row"><?php esc_html_e( 'Tax Refunded Amount', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
<th class="total_row"><?php esc_html_e( 'Final Tax Amount ', 'woocommerce-eu-vat-number' ); ?></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$found = false;
|
||||
$total_amount = 0;
|
||||
$total_refunded_amount = 0;
|
||||
$total_final_amount = 0;
|
||||
$total_tax_amount = 0;
|
||||
$total_refunded_tax_amount = 0;
|
||||
$total_final_tax_amount = 0;
|
||||
|
||||
foreach ( $grouped_tax_rows as $rate_id => $tax_row ) {
|
||||
if ( is_numeric( $rate_id ) ) {
|
||||
$rate = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}woocommerce_tax_rates WHERE tax_rate_id = %d;", $rate_id ) );
|
||||
|
||||
if ( ! is_object( $rate ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$country = $rate->tax_rate_country;
|
||||
|
||||
/**
|
||||
* Filters tax rate for the reports
|
||||
*
|
||||
* @since 2.1.7
|
||||
*
|
||||
* @param string $rate->tax_rate Tax Rate.
|
||||
* @param int $rate_id Rate Id.
|
||||
* @param object $tax_row Tax Row.
|
||||
*/
|
||||
$tax_rate = apply_filters( 'woocommerce_reports_taxes_rate', $rate->tax_rate, $rate_id, $tax_row ) . '%';
|
||||
} else {
|
||||
$country = $rate_id;
|
||||
$tax_rate = '-';
|
||||
}
|
||||
|
||||
if ( in_array( $country, WC_EU_VAT_Number::get_eu_countries(), true ) || empty( WC()->countries->countries[ $country ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$found = true;
|
||||
$total_amount += $tax_row->amount;
|
||||
$total_refunded_amount += $tax_row->refunded_amount;
|
||||
$total_final_amount += $tax_row->amount + $tax_row->refunded_amount;
|
||||
$total_tax_amount += $tax_row->tax_amount;
|
||||
$total_refunded_tax_amount += $tax_row->refunded_tax_amount;
|
||||
$total_final_tax_amount += $tax_row->tax_amount + $tax_row->refunded_tax_amount;
|
||||
// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
?>
|
||||
<tr>
|
||||
<th scope="row"><?php echo esc_html( WC()->countries->countries[ $country ] ); ?></th>
|
||||
<th scope="row"><?php echo esc_html( $country ); ?></th>
|
||||
<td><?php echo esc_html( $tax_rate ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $tax_row->amount ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $tax_row->refunded_amount * -1 ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $tax_row->amount + $tax_row->refunded_amount ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $tax_row->tax_amount ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $tax_row->refunded_tax_amount * -1 ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $tax_row->tax_amount + $tax_row->refunded_tax_amount ); ?></td>
|
||||
</tr>
|
||||
<?php
|
||||
// phpcs:enable
|
||||
}
|
||||
|
||||
if ( $found ) {
|
||||
// phpcs:disable WordPress.Security.EscapeOutput.OutputNotEscaped
|
||||
?>
|
||||
<tr>
|
||||
<th><strong><?php esc_html_e( 'Totals', 'woocommerce-eu-vat-number' ); ?></strong></th>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<td class="total_row"><?php echo wc_price( $total_amount ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $total_refunded_amount * -1 ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $total_final_amount ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $total_tax_amount ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $total_refunded_tax_amount * -1 ); ?></td>
|
||||
<td class="total_row"><?php echo wc_price( $total_final_tax_amount ); ?></td>
|
||||
</tr>
|
||||
<?php
|
||||
// phpcs:enable
|
||||
} else {
|
||||
?>
|
||||
<tr>
|
||||
<td colspan="9"><?php esc_html_e( 'No non-eu sales found in this period', 'woocommerce-eu-vat-number' ); ?></td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,55 +1,55 @@
|
|||
<?php
|
||||
/**
|
||||
* List of countries to consider under EU.
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the EU Country codes.
|
||||
*
|
||||
* @since 2.3.6
|
||||
*
|
||||
* @param array $country_codes Country codes.
|
||||
*/
|
||||
return apply_filters(
|
||||
'woocommerce_eu_vat_number_country_codes',
|
||||
array(
|
||||
'AT',
|
||||
'BE',
|
||||
'BG',
|
||||
'CY',
|
||||
'CZ',
|
||||
'DE',
|
||||
'DK',
|
||||
'EE',
|
||||
'ES',
|
||||
'FI',
|
||||
'FR',
|
||||
'GB',
|
||||
'GR',
|
||||
'HR',
|
||||
'HU',
|
||||
'IE',
|
||||
'IT',
|
||||
'LT',
|
||||
'LU',
|
||||
'LV',
|
||||
'MT',
|
||||
'NL',
|
||||
'PL',
|
||||
'PT',
|
||||
'RO',
|
||||
'SE',
|
||||
'SI',
|
||||
'SK',
|
||||
'MC',
|
||||
'IM',
|
||||
)
|
||||
);
|
||||
<?php
|
||||
/**
|
||||
* List of countries to consider under EU.
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
* @since 1.0.0
|
||||
* @return void
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters the EU Country codes.
|
||||
*
|
||||
* @since 2.3.6
|
||||
*
|
||||
* @param array $country_codes Country codes.
|
||||
*/
|
||||
return apply_filters(
|
||||
'woocommerce_eu_vat_number_country_codes',
|
||||
array(
|
||||
'AT',
|
||||
'BE',
|
||||
'BG',
|
||||
'CY',
|
||||
'CZ',
|
||||
'DE',
|
||||
'DK',
|
||||
'EE',
|
||||
'ES',
|
||||
'FI',
|
||||
'FR',
|
||||
'GB',
|
||||
'GR',
|
||||
'HR',
|
||||
'HU',
|
||||
'IE',
|
||||
'IT',
|
||||
'LT',
|
||||
'LU',
|
||||
'LV',
|
||||
'MT',
|
||||
'NL',
|
||||
'PL',
|
||||
'PT',
|
||||
'RO',
|
||||
'SE',
|
||||
'SI',
|
||||
'SK',
|
||||
'MC',
|
||||
'IM',
|
||||
)
|
||||
);
|
||||
|
|
|
@ -1,104 +1,104 @@
|
|||
<?php
|
||||
/**
|
||||
* List settings for the extension.
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$tax_classes = WC_Tax::get_tax_classes();
|
||||
|
||||
$classes_options = array();
|
||||
$classes_options['standard'] = __( 'Standard', 'woocommerce-eu-vat-number' );
|
||||
|
||||
foreach ( $tax_classes as $class ) {
|
||||
$classes_options[ sanitize_title( $class ) ] = esc_html( $class );
|
||||
}
|
||||
|
||||
return array(
|
||||
array(
|
||||
'type' => 'sectionend',
|
||||
),
|
||||
array(
|
||||
'type' => 'title',
|
||||
'title' => __( 'EU VAT Number Handling', 'woocommerce-eu-vat-number' ),
|
||||
'id' => 'vat_number',
|
||||
),
|
||||
array(
|
||||
'name' => __( 'VAT Number Field Label', 'woocommerce-eu-vat-number' ),
|
||||
'desc' => __( 'The label that appears at checkout for the VAT number field.', 'woocommerce-eu-vat-number' ),
|
||||
'id' => 'woocommerce_eu_vat_number_field_label',
|
||||
'type' => 'text',
|
||||
'default' => _x( 'VAT number', 'Default Field Label', 'woocommerce-eu-vat-number' ),
|
||||
'placeholder' => _x( 'VAT number', 'Default Field Label', 'woocommerce-eu-vat-number' ),
|
||||
'desc_tip' => true,
|
||||
),
|
||||
array(
|
||||
'name' => __( 'VAT Number Field Description', 'woocommerce-eu-vat-number' ),
|
||||
'desc' => __( 'The description that appears at checkout below the VAT number field.', 'woocommerce-eu-vat-number' ),
|
||||
'id' => 'woocommerce_eu_vat_number_field_description',
|
||||
'type' => 'text',
|
||||
'desc_tip' => true,
|
||||
),
|
||||
array(
|
||||
'name' => __( 'Remove VAT for Businesses in Your Base Country', 'woocommerce-eu-vat-number' ),
|
||||
'desc' => __( 'Remove the VAT from the order even when the customer is in your base country.', 'woocommerce-eu-vat-number' ),
|
||||
'id' => 'woocommerce_eu_vat_number_deduct_in_base',
|
||||
'type' => 'checkbox',
|
||||
'default' => 'yes',
|
||||
),
|
||||
array(
|
||||
'name' => __( 'Failed Validation Handling', 'woocommerce-eu-vat-number' ),
|
||||
'desc' => __( 'This option determines how orders are handled if the VAT number does not pass validation.', 'woocommerce-eu-vat-number' ),
|
||||
'id' => 'woocommerce_eu_vat_number_failure_handling',
|
||||
'desc_tip' => true,
|
||||
'type' => 'select',
|
||||
'options' => array(
|
||||
'reject' => __( 'Reject the order and show the customer an error message', 'woocommerce-eu-vat-number' ),
|
||||
'accept_with_vat' => __( 'Accept the order, but do not remove VAT.', 'woocommerce-eu-vat-number' ),
|
||||
'accept' => __( 'Accept the order and remove VAT.', 'woocommerce-eu-vat-number' ),
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => __( 'Enable B2B Transactions', 'woocommerce-eu-vat-number' ),
|
||||
'desc' => __( 'This will force users to check out with a VAT number, useful for sites that transact purely from B2B.', 'woocommerce-eu-vat-number' ),
|
||||
'id' => 'woocommerce_eu_vat_number_b2b',
|
||||
'type' => 'checkbox',
|
||||
'default' => 'no',
|
||||
),
|
||||
array(
|
||||
'type' => 'sectionend',
|
||||
),
|
||||
array(
|
||||
'type' => 'title',
|
||||
'title' => __( 'EU VAT Digital Goods Handling', 'woocommerce-eu-vat-number' ),
|
||||
/* translators: %1$s Opening anchor tag, %2$s Closing anchor tag */
|
||||
'desc' => sprintf( __( 'EU VAT laws are changing for digital goods from the 1st Jan 2015 (affecting B2C transactions only). The VAT on digital goods must be calculated based on the customer location, and you need to collect evidence of this (IP address and Billing Address). You also need to setup VAT rates to charge the correct amount. %1$sRead this guide%2$s for instructions on doing this.', 'woocommerce-eu-vat-number' ), '<a href="https://docs.woocommerce.com/document/setting-up-eu-vat-rates-for-digital-products">', '</a>' ),
|
||||
'id' => 'vat_number_digital_goods',
|
||||
),
|
||||
array(
|
||||
'name' => __( 'Tax Classes for Digital Goods', 'woocommerce-eu-vat-number' ),
|
||||
'desc' => __( 'This option tells the plugin which of your tax classes are for digital goods. This affects the taxable location of the user as of 1st Jan 2015.', 'woocommerce-eu-vat-number' ),
|
||||
'id' => 'woocommerce_eu_vat_number_digital_tax_classes',
|
||||
'desc_tip' => true,
|
||||
'type' => 'multiselect',
|
||||
'class' => 'chosen_select wp-enhanced-select',
|
||||
'css' => 'width: 450px;',
|
||||
'default' => '',
|
||||
'options' => $classes_options,
|
||||
'custom_attributes' => array(
|
||||
'data-placeholder' => __( 'Select some tax classes', 'woocommerce-eu-vat-number' ),
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => __( 'Collect and Validate Evidence', 'woocommerce-eu-vat-number' ),
|
||||
'desc' => __( 'This validates the customer IP address against their billing address, and prompts the customer to self-declare their address if they do not match. Applies to digital goods and services only.', 'woocommerce-eu-vat-number' ),
|
||||
'id' => 'woocommerce_eu_vat_number_validate_ip',
|
||||
'type' => 'checkbox',
|
||||
'default' => 'no',
|
||||
),
|
||||
);
|
||||
<?php
|
||||
/**
|
||||
* List settings for the extension.
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
* @since 1.0.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$tax_classes = WC_Tax::get_tax_classes();
|
||||
|
||||
$classes_options = array();
|
||||
$classes_options['standard'] = __( 'Standard', 'woocommerce-eu-vat-number' );
|
||||
|
||||
foreach ( $tax_classes as $class ) {
|
||||
$classes_options[ sanitize_title( $class ) ] = esc_html( $class );
|
||||
}
|
||||
|
||||
return array(
|
||||
array(
|
||||
'type' => 'sectionend',
|
||||
),
|
||||
array(
|
||||
'type' => 'title',
|
||||
'title' => __( 'EU VAT Number Handling', 'woocommerce-eu-vat-number' ),
|
||||
'id' => 'vat_number',
|
||||
),
|
||||
array(
|
||||
'name' => __( 'VAT Number Field Label', 'woocommerce-eu-vat-number' ),
|
||||
'desc' => __( 'The label that appears at checkout for the VAT number field.', 'woocommerce-eu-vat-number' ),
|
||||
'id' => 'woocommerce_eu_vat_number_field_label',
|
||||
'type' => 'text',
|
||||
'default' => _x( 'VAT number', 'Default Field Label', 'woocommerce-eu-vat-number' ),
|
||||
'placeholder' => _x( 'VAT number', 'Default Field Label', 'woocommerce-eu-vat-number' ),
|
||||
'desc_tip' => true,
|
||||
),
|
||||
array(
|
||||
'name' => __( 'VAT Number Field Description', 'woocommerce-eu-vat-number' ),
|
||||
'desc' => __( 'The description that appears at checkout below the VAT number field.', 'woocommerce-eu-vat-number' ),
|
||||
'id' => 'woocommerce_eu_vat_number_field_description',
|
||||
'type' => 'text',
|
||||
'desc_tip' => true,
|
||||
),
|
||||
array(
|
||||
'name' => __( 'Remove VAT for Businesses in Your Base Country', 'woocommerce-eu-vat-number' ),
|
||||
'desc' => __( 'Remove the VAT from the order even when the customer is in your base country.', 'woocommerce-eu-vat-number' ),
|
||||
'id' => 'woocommerce_eu_vat_number_deduct_in_base',
|
||||
'type' => 'checkbox',
|
||||
'default' => 'yes',
|
||||
),
|
||||
array(
|
||||
'name' => __( 'Failed Validation Handling', 'woocommerce-eu-vat-number' ),
|
||||
'desc' => __( 'This option determines how orders are handled if the VAT number does not pass validation.', 'woocommerce-eu-vat-number' ),
|
||||
'id' => 'woocommerce_eu_vat_number_failure_handling',
|
||||
'desc_tip' => true,
|
||||
'type' => 'select',
|
||||
'options' => array(
|
||||
'reject' => __( 'Reject the order and show the customer an error message', 'woocommerce-eu-vat-number' ),
|
||||
'accept_with_vat' => __( 'Accept the order, but do not remove VAT.', 'woocommerce-eu-vat-number' ),
|
||||
'accept' => __( 'Accept the order and remove VAT.', 'woocommerce-eu-vat-number' ),
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => __( 'Enable B2B Transactions', 'woocommerce-eu-vat-number' ),
|
||||
'desc' => __( 'This will force users to check out with a VAT number, useful for sites that transact purely from B2B.', 'woocommerce-eu-vat-number' ),
|
||||
'id' => 'woocommerce_eu_vat_number_b2b',
|
||||
'type' => 'checkbox',
|
||||
'default' => 'no',
|
||||
),
|
||||
array(
|
||||
'type' => 'sectionend',
|
||||
),
|
||||
array(
|
||||
'type' => 'title',
|
||||
'title' => __( 'EU VAT Digital Goods Handling', 'woocommerce-eu-vat-number' ),
|
||||
/* translators: %1$s Opening anchor tag, %2$s Closing anchor tag */
|
||||
'desc' => sprintf( __( 'EU VAT laws are changing for digital goods from the 1st Jan 2015 (affecting B2C transactions only). The VAT on digital goods must be calculated based on the customer location, and you need to collect evidence of this (IP address and Billing Address). You also need to setup VAT rates to charge the correct amount. %1$sRead this guide%2$s for instructions on doing this.', 'woocommerce-eu-vat-number' ), '<a href="https://docs.woocommerce.com/document/setting-up-eu-vat-rates-for-digital-products">', '</a>' ),
|
||||
'id' => 'vat_number_digital_goods',
|
||||
),
|
||||
array(
|
||||
'name' => __( 'Tax Classes for Digital Goods', 'woocommerce-eu-vat-number' ),
|
||||
'desc' => __( 'This option tells the plugin which of your tax classes are for digital goods. This affects the taxable location of the user as of 1st Jan 2015.', 'woocommerce-eu-vat-number' ),
|
||||
'id' => 'woocommerce_eu_vat_number_digital_tax_classes',
|
||||
'desc_tip' => true,
|
||||
'type' => 'multiselect',
|
||||
'class' => 'chosen_select wp-enhanced-select',
|
||||
'css' => 'width: 450px;',
|
||||
'default' => '',
|
||||
'options' => $classes_options,
|
||||
'custom_attributes' => array(
|
||||
'data-placeholder' => __( 'Select some tax classes', 'woocommerce-eu-vat-number' ),
|
||||
),
|
||||
),
|
||||
array(
|
||||
'name' => __( 'Collect and Validate Evidence', 'woocommerce-eu-vat-number' ),
|
||||
'desc' => __( 'This validates the customer IP address against their billing address, and prompts the customer to self-declare their address if they do not match. Applies to digital goods and services only.', 'woocommerce-eu-vat-number' ),
|
||||
'id' => 'woocommerce_eu_vat_number_validate_ip',
|
||||
'type' => 'checkbox',
|
||||
'default' => 'no',
|
||||
),
|
||||
);
|
||||
|
|
|
@ -1,100 +1,100 @@
|
|||
<?php
|
||||
/**
|
||||
* VIES Client
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once dirname( __FILE__ ) . '/class-vies-response.php';
|
||||
|
||||
/**
|
||||
* A client for the VIES SOAP web service
|
||||
*
|
||||
* Based on https://github.com/ddeboer/vatin
|
||||
*/
|
||||
class VIES_Client {
|
||||
|
||||
/**
|
||||
* URL to WSDL
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $wsdl = 'https://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl';
|
||||
|
||||
/**
|
||||
* SOAP client
|
||||
*
|
||||
* @var SoapClient
|
||||
*/
|
||||
protected $soapclient;
|
||||
|
||||
/**
|
||||
* SOAP classmap
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $classmap = array(
|
||||
'checkVatResponse' => 'VIES_Response',
|
||||
);
|
||||
|
||||
/**
|
||||
* Check VAT
|
||||
*
|
||||
* @param string $country_code Country code.
|
||||
* @param string $vat_number VAT number.
|
||||
*
|
||||
* @return VIES_Response
|
||||
*/
|
||||
public function check_vat( $country_code, $vat_number ) {
|
||||
return $this->get_soap_client()->checkVat(
|
||||
array(
|
||||
'countryCode' => $country_code,
|
||||
'vatNumber' => $vat_number,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get SOAP client
|
||||
*
|
||||
* @return SoapClient
|
||||
*/
|
||||
public function get_soap_client() {
|
||||
|
||||
/**
|
||||
* Filters SoapClient Parameters.
|
||||
*
|
||||
* @since 2.3.7
|
||||
*
|
||||
* @param array $args SoapClient Parameters.
|
||||
*/
|
||||
$soap_parameters = apply_filters(
|
||||
'woocommerce_eu_vat_number_soap_parameters',
|
||||
array(
|
||||
'classmap' => $this->classmap,
|
||||
'cache_wsdl' => WSDL_CACHE_BOTH,
|
||||
'connection_timeout' => 45,
|
||||
'user_agent' => 'Mozilla', // the request fails unless a (dummy) user agent is specified.
|
||||
)
|
||||
);
|
||||
|
||||
if ( null === $this->soapclient ) {
|
||||
try {
|
||||
$this->soapclient = new SoapClient(
|
||||
$this->wsdl,
|
||||
$soap_parameters
|
||||
);
|
||||
} catch ( Exception $e ) {
|
||||
return new WP_Error( 'api', __( 'Error communicating with the VAT validation server - please try again.', 'woocommerce-eu-vat-number' ) );
|
||||
}
|
||||
}
|
||||
|
||||
return $this->soapclient;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
<?php
|
||||
/**
|
||||
* VIES Client
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
require_once dirname( __FILE__ ) . '/class-vies-response.php';
|
||||
|
||||
/**
|
||||
* A client for the VIES SOAP web service
|
||||
*
|
||||
* Based on https://github.com/ddeboer/vatin
|
||||
*/
|
||||
class VIES_Client {
|
||||
|
||||
/**
|
||||
* URL to WSDL
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $wsdl = 'https://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl';
|
||||
|
||||
/**
|
||||
* SOAP client
|
||||
*
|
||||
* @var SoapClient
|
||||
*/
|
||||
protected $soapclient;
|
||||
|
||||
/**
|
||||
* SOAP classmap
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $classmap = array(
|
||||
'checkVatResponse' => 'VIES_Response',
|
||||
);
|
||||
|
||||
/**
|
||||
* Check VAT
|
||||
*
|
||||
* @param string $country_code Country code.
|
||||
* @param string $vat_number VAT number.
|
||||
*
|
||||
* @return VIES_Response
|
||||
*/
|
||||
public function check_vat( $country_code, $vat_number ) {
|
||||
return $this->get_soap_client()->checkVat(
|
||||
array(
|
||||
'countryCode' => $country_code,
|
||||
'vatNumber' => $vat_number,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get SOAP client
|
||||
*
|
||||
* @return SoapClient
|
||||
*/
|
||||
public function get_soap_client() {
|
||||
|
||||
/**
|
||||
* Filters SoapClient Parameters.
|
||||
*
|
||||
* @since 2.3.7
|
||||
*
|
||||
* @param array $args SoapClient Parameters.
|
||||
*/
|
||||
$soap_parameters = apply_filters(
|
||||
'woocommerce_eu_vat_number_soap_parameters',
|
||||
array(
|
||||
'classmap' => $this->classmap,
|
||||
'cache_wsdl' => WSDL_CACHE_BOTH,
|
||||
'connection_timeout' => 45,
|
||||
'user_agent' => 'Mozilla', // the request fails unless a (dummy) user agent is specified.
|
||||
)
|
||||
);
|
||||
|
||||
if ( null === $this->soapclient ) {
|
||||
try {
|
||||
$this->soapclient = new SoapClient(
|
||||
$this->wsdl,
|
||||
$soap_parameters
|
||||
);
|
||||
} catch ( Exception $e ) {
|
||||
return new WP_Error( 'api', __( 'Error communicating with the VAT validation server - please try again.', 'woocommerce-eu-vat-number' ) );
|
||||
}
|
||||
}
|
||||
|
||||
return $this->soapclient;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,117 +1,117 @@
|
|||
<?php
|
||||
/**
|
||||
* VIES Response
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
* @phpcs:disable WordPress.NamingConventions.ValidVariableName
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Response object from VIES
|
||||
*/
|
||||
class VIES_Response {
|
||||
/**
|
||||
* Country Code
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $countryCode;
|
||||
|
||||
/**
|
||||
* VAT Number
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $vatNumber;
|
||||
|
||||
/**
|
||||
* Date of request.
|
||||
*
|
||||
* @var DateTime
|
||||
*/
|
||||
protected $requestDate;
|
||||
|
||||
/**
|
||||
* Is VAT valid?
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $valid;
|
||||
|
||||
/**
|
||||
* Name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* Address
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $address;
|
||||
|
||||
/**
|
||||
* Get the country code
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_country_code() {
|
||||
return $this->countryCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the VAT Number
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_vat_number() {
|
||||
return $this->vatNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the date of the request
|
||||
*
|
||||
* @return DateTime
|
||||
*/
|
||||
public function get_request_date() {
|
||||
if ( ! $this->requestDate instanceof DateTime ) {
|
||||
$this->requestDate = new DateTime( $this->requestDate );
|
||||
}
|
||||
return $this->requestDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the number is valid or not
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_valid() {
|
||||
return $this->valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_name() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the address
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_address() {
|
||||
return $this->address;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
<?php
|
||||
/**
|
||||
* VIES Response
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
* @phpcs:disable WordPress.NamingConventions.ValidVariableName
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Response object from VIES
|
||||
*/
|
||||
class VIES_Response {
|
||||
/**
|
||||
* Country Code
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $countryCode;
|
||||
|
||||
/**
|
||||
* VAT Number
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $vatNumber;
|
||||
|
||||
/**
|
||||
* Date of request.
|
||||
*
|
||||
* @var DateTime
|
||||
*/
|
||||
protected $requestDate;
|
||||
|
||||
/**
|
||||
* Is VAT valid?
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $valid;
|
||||
|
||||
/**
|
||||
* Name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $name;
|
||||
|
||||
/**
|
||||
* Address
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $address;
|
||||
|
||||
/**
|
||||
* Get the country code
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_country_code() {
|
||||
return $this->countryCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the VAT Number
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_vat_number() {
|
||||
return $this->vatNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the date of the request
|
||||
*
|
||||
* @return DateTime
|
||||
*/
|
||||
public function get_request_date() {
|
||||
if ( ! $this->requestDate instanceof DateTime ) {
|
||||
$this->requestDate = new DateTime( $this->requestDate );
|
||||
}
|
||||
return $this->requestDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the number is valid or not
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function is_valid() {
|
||||
return $this->valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_name() {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the address
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_address() {
|
||||
return $this->address;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,79 +1,79 @@
|
|||
<?php
|
||||
/**
|
||||
* General functions.
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gets the VAT ID from order.
|
||||
*
|
||||
* @since 2.3.21
|
||||
* @param object $order The order in context.
|
||||
* @return string $vat;
|
||||
*/
|
||||
function wc_eu_vat_get_vat_from_order( $order ) {
|
||||
if ( ! $order ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$vat = $order->get_meta( '_billing_vat_number', true ) ? $order->get_meta( '_billing_vat_number', true ) : '';
|
||||
|
||||
if ( ! $vat ) {
|
||||
$vat = $order->get_meta( '_vat_number', true ) ? $order->get_meta( '_vat_number', true ) : '';
|
||||
}
|
||||
|
||||
return $vat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display 0.00% VAT line item and reason.
|
||||
*
|
||||
* @param array $total_rows Order item totals array.
|
||||
* @param WC_Order $order WC_Order object.
|
||||
* @param string $tax_display Tax display (incl or excl).
|
||||
*/
|
||||
function wc_eu_vat_maybe_add_zero_tax_display( $total_rows, $order, $tax_display ) {
|
||||
// Display in Email and Invoice only.
|
||||
if ( is_account_page() ) {
|
||||
return $total_rows;
|
||||
}
|
||||
|
||||
$is_vat_exempt = ( 'yes' === $order->get_meta( 'is_vat_exempt' ) );
|
||||
$is_valid = wc_string_to_bool( $order->get_meta( '_vat_number_is_valid', true ) );
|
||||
|
||||
// Check if VAT number is valid and tax is exempted.
|
||||
if ( wc_tax_enabled() && $is_vat_exempt && $is_valid && empty( $order->get_tax_totals() ) ) {
|
||||
/**
|
||||
* Filters the reason for zero tax.
|
||||
*
|
||||
* @since 2.8.1
|
||||
*/
|
||||
$zero_tax_reason = apply_filters( 'wc_eu_vat_number_zero_tax_reason', __( 'Supply of services subject to reverse charge', 'woocommerce-eu-vat-number' ) );
|
||||
$display_tax_reason = '<br/><small>' . esc_html( $zero_tax_reason ) . '</small>';
|
||||
|
||||
if ( 'excl' === $tax_display ) {
|
||||
if ( 'itemized' === get_option( 'woocommerce_tax_total_display' ) ) {
|
||||
$tax_line_item = array(
|
||||
'tax' => array(
|
||||
'label' => WC()->countries->tax_or_vat() . ':',
|
||||
'value' => wc_price( $order->get_total_tax(), array( 'currency' => $order->get_currency() ) ) . $display_tax_reason,
|
||||
),
|
||||
);
|
||||
|
||||
// Add zero tax line item before grand total.
|
||||
array_splice( $total_rows, count( $total_rows ) - 1, 0, $tax_line_item );
|
||||
} elseif ( isset( $total_rows['tax'] ) && isset( $total_rows['tax']['value'] ) ) {
|
||||
$total_rows['tax']['value'] = $total_rows['tax']['value'] . $display_tax_reason;
|
||||
}
|
||||
} elseif ( 'incl' === $tax_display ) {
|
||||
// translators: %1$s: Tax label (VAT or Tax).
|
||||
$append_zero_tax = sprintf( esc_html__( ' (inc. 0.00%% %1$s) ', 'woocommerce-eu-vat-number' ), WC()->countries->tax_or_vat() ) . $display_tax_reason;
|
||||
|
||||
// Append zero tax details to Grand Total.
|
||||
$total_rows['order_total']['value'] = $total_rows['order_total']['value'] . $append_zero_tax;
|
||||
}
|
||||
}
|
||||
|
||||
return $total_rows;
|
||||
}
|
||||
<?php
|
||||
/**
|
||||
* General functions.
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gets the VAT ID from order.
|
||||
*
|
||||
* @since 2.3.21
|
||||
* @param object $order The order in context.
|
||||
* @return string $vat;
|
||||
*/
|
||||
function wc_eu_vat_get_vat_from_order( $order ) {
|
||||
if ( ! $order ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$vat = $order->get_meta( '_billing_vat_number', true ) ? $order->get_meta( '_billing_vat_number', true ) : '';
|
||||
|
||||
if ( ! $vat ) {
|
||||
$vat = $order->get_meta( '_vat_number', true ) ? $order->get_meta( '_vat_number', true ) : '';
|
||||
}
|
||||
|
||||
return $vat;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display 0.00% VAT line item and reason.
|
||||
*
|
||||
* @param array $total_rows Order item totals array.
|
||||
* @param WC_Order $order WC_Order object.
|
||||
* @param string $tax_display Tax display (incl or excl).
|
||||
*/
|
||||
function wc_eu_vat_maybe_add_zero_tax_display( $total_rows, $order, $tax_display ) {
|
||||
// Display in Email and Invoice only.
|
||||
if ( is_account_page() ) {
|
||||
return $total_rows;
|
||||
}
|
||||
|
||||
$is_vat_exempt = ( 'yes' === $order->get_meta( 'is_vat_exempt' ) );
|
||||
$is_valid = wc_string_to_bool( $order->get_meta( '_vat_number_is_valid', true ) );
|
||||
|
||||
// Check if VAT number is valid and tax is exempted.
|
||||
if ( wc_tax_enabled() && $is_vat_exempt && $is_valid && empty( $order->get_tax_totals() ) ) {
|
||||
/**
|
||||
* Filters the reason for zero tax.
|
||||
*
|
||||
* @since 2.8.1
|
||||
*/
|
||||
$zero_tax_reason = apply_filters( 'wc_eu_vat_number_zero_tax_reason', __( 'Supply of services subject to reverse charge', 'woocommerce-eu-vat-number' ) );
|
||||
$display_tax_reason = '<br/><small>' . esc_html( $zero_tax_reason ) . '</small>';
|
||||
|
||||
if ( 'excl' === $tax_display ) {
|
||||
if ( 'itemized' === get_option( 'woocommerce_tax_total_display' ) ) {
|
||||
$tax_line_item = array(
|
||||
'tax' => array(
|
||||
'label' => WC()->countries->tax_or_vat() . ':',
|
||||
'value' => wc_price( $order->get_total_tax(), array( 'currency' => $order->get_currency() ) ) . $display_tax_reason,
|
||||
),
|
||||
);
|
||||
|
||||
// Add zero tax line item before grand total.
|
||||
array_splice( $total_rows, count( $total_rows ) - 1, 0, $tax_line_item );
|
||||
} elseif ( isset( $total_rows['tax'] ) && isset( $total_rows['tax']['value'] ) ) {
|
||||
$total_rows['tax']['value'] = $total_rows['tax']['value'] . $display_tax_reason;
|
||||
}
|
||||
} elseif ( 'incl' === $tax_display ) {
|
||||
// translators: %1$s: Tax label (VAT or Tax).
|
||||
$append_zero_tax = sprintf( esc_html__( ' (inc. 0.00%% %1$s) ', 'woocommerce-eu-vat-number' ), WC()->countries->tax_or_vat() ) . $display_tax_reason;
|
||||
|
||||
// Append zero tax details to Grand Total.
|
||||
$total_rows['order_total']['value'] = $total_rows['order_total']['value'] . $append_zero_tax;
|
||||
}
|
||||
}
|
||||
|
||||
return $total_rows;
|
||||
}
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
# This file is distributed under the GNU General Public License v3.0.
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: WooCommerce EU VAT Number 2.8.3\n"
|
||||
"Project-Id-Version: WooCommerce EU VAT Number 2.8.8\n"
|
||||
"Report-Msgid-Bugs-To: "
|
||||
"https://wordpress.org/support/plugin/woocommerce-eu-vat-number\n"
|
||||
"POT-Creation-Date: 2023-04-03 17:24:12+00:00\n"
|
||||
"POT-Creation-Date: 2023-09-18 02:12:29+00:00\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=utf-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
@ -22,8 +22,8 @@ msgstr ""
|
|||
#: includes/class-wc-eu-vat-my-account.php:207
|
||||
#: includes/class-wc-eu-vat-my-account.php:218
|
||||
#: includes/class-wc-eu-vat-number.php:186
|
||||
#: includes/class-wc-eu-vat-number.php:710
|
||||
#: includes/class-wc-eu-vat-number.php:724
|
||||
#: includes/class-wc-eu-vat-number.php:709
|
||||
#: includes/class-wc-eu-vat-number.php:723
|
||||
#: includes/class-wc-eu-vat-privacy.php:147
|
||||
#: includes/class-wc-eu-vat-report-ec-sales-list.php:215
|
||||
msgid "VAT number"
|
||||
|
@ -83,14 +83,14 @@ msgstr ""
|
|||
|
||||
#: includes/class-wc-eu-vat-admin.php:368
|
||||
#: includes/class-wc-eu-vat-my-account.php:218
|
||||
#: includes/class-wc-eu-vat-number.php:710
|
||||
#: includes/class-wc-eu-vat-number.php:709
|
||||
#. translators: %1$s VAT number field label, %2$s VAT number, %3$s Billing
|
||||
#. Country.
|
||||
#. translators: 1: VAT number field label, 2: VAT Number, 3: Billing country
|
||||
msgid "You have entered an invalid %1$s (%2$s) for your billing country (%3$s)."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-wc-eu-vat-admin.php:463
|
||||
#: includes/class-wc-eu-vat-admin.php:464
|
||||
#. translators: %1$s Opening strong tag, %2$s Closing strong tag, %3$s Break
|
||||
#. tag.
|
||||
msgid ""
|
||||
|
@ -102,7 +102,7 @@ msgid ""
|
|||
"from %1$sNorthern Ireland%2$s."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-wc-eu-vat-admin.php:474
|
||||
#: includes/class-wc-eu-vat-admin.php:475
|
||||
#. translators: %1$s Opening strong tag, %2$s Closing strong tag.
|
||||
msgid ""
|
||||
"By using %1$sWooCommerce EU VAT Number%2$s plugin, you've agreed that the "
|
||||
|
@ -111,19 +111,19 @@ msgid ""
|
|||
"tax specific questions."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-wc-eu-vat-admin.php:479
|
||||
#: includes/class-wc-eu-vat-admin.php:480
|
||||
msgid "I understand"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-wc-eu-vat-blocks.php:196
|
||||
#: includes/class-wc-eu-vat-blocks.php:197
|
||||
msgid "Location confirmation."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-wc-eu-vat-blocks.php:246
|
||||
#: includes/class-wc-eu-vat-blocks.php:247
|
||||
msgid "Invalid VAT number."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-wc-eu-vat-blocks.php:325
|
||||
#: includes/class-wc-eu-vat-blocks.php:326
|
||||
msgid "VAT Data"
|
||||
msgstr ""
|
||||
|
||||
|
@ -150,11 +150,11 @@ msgstr ""
|
|||
msgid "VAT number updated successfully!"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-wc-eu-vat-number.php:275
|
||||
#: includes/class-wc-eu-vat-number.php:277
|
||||
msgid "VAT number is required."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-wc-eu-vat-number.php:281
|
||||
#: includes/class-wc-eu-vat-number.php:283
|
||||
#. translators: %1$s - VAT number field label, %2$s - VAT Number from user,
|
||||
#. %3$s - Billing country.
|
||||
msgid ""
|
||||
|
@ -162,23 +162,23 @@ msgid ""
|
|||
"country (%3$s)."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-wc-eu-vat-number.php:295
|
||||
#: includes/class-wc-eu-vat-number.php:313
|
||||
#: includes/class-wc-eu-vat-number.php:297
|
||||
#: includes/class-wc-eu-vat-number.php:315
|
||||
#: includes/vies/class-vies-client.php:92
|
||||
msgid "Error communicating with the VAT validation server - please try again."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-wc-eu-vat-number.php:580
|
||||
#: includes/class-wc-eu-vat-number.php:582
|
||||
#. translators: %s: VAT Number
|
||||
msgid "VAT Number: %s"
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-wc-eu-vat-number.php:724
|
||||
#: includes/class-wc-eu-vat-number.php:723
|
||||
#. translators: 1: VAT number field label, 2: Billing country
|
||||
msgid "%1$s is a required field for your billing country (%2$s)."
|
||||
msgstr ""
|
||||
|
||||
#: includes/class-wc-eu-vat-number.php:737
|
||||
#: includes/class-wc-eu-vat-number.php:736
|
||||
#. translators: 1: Ip Address.
|
||||
msgid ""
|
||||
"Your IP Address (%1$s) does not match your billing country (%2$s). European "
|
||||
|
@ -466,27 +466,27 @@ msgstr ""
|
|||
msgid "Save"
|
||||
msgstr ""
|
||||
|
||||
#: woocommerce-eu-vat-number.php:154 woocommerce-eu-vat-number.php:166
|
||||
#: woocommerce-eu-vat-number.php:177
|
||||
#: woocommerce-eu-vat-number.php:171 woocommerce-eu-vat-number.php:183
|
||||
#: woocommerce-eu-vat-number.php:194 woocommerce-eu-vat-number.php:241
|
||||
#. translators: %1$s: Plugin page link start %2$s Link end
|
||||
#. translators: %1$s: Minimum version %2$s: Plugin page link start %3$s Link
|
||||
#. end
|
||||
msgid "WooCommerce EU VAT Number is inactive."
|
||||
msgstr ""
|
||||
|
||||
#: woocommerce-eu-vat-number.php:154
|
||||
#: woocommerce-eu-vat-number.php:171
|
||||
msgid ""
|
||||
"The WooCommerce plugin must be active for EU VAT Number to work. %1$sPlease "
|
||||
"install and activate WooCommerce%2$s."
|
||||
msgstr ""
|
||||
|
||||
#: woocommerce-eu-vat-number.php:166
|
||||
#: woocommerce-eu-vat-number.php:183
|
||||
msgid ""
|
||||
"The WooCommerce plugin must be at least version %1$s for EU VAT Number to "
|
||||
"work. %2$sPlease upgrade WooCommerce%3$s."
|
||||
msgstr ""
|
||||
|
||||
#: woocommerce-eu-vat-number.php:177
|
||||
#: woocommerce-eu-vat-number.php:194
|
||||
msgid ""
|
||||
"Your server does not provide SOAP support which is required functionality "
|
||||
"for communicating with VIES. You will need to reach out to your web hosting "
|
||||
|
@ -494,31 +494,39 @@ msgid ""
|
|||
"server."
|
||||
msgstr ""
|
||||
|
||||
#: woocommerce-eu-vat-number.php:254
|
||||
#: woocommerce-eu-vat-number.php:245
|
||||
#. translators: %1$s: Settings link start %2$s: Link end
|
||||
msgid ""
|
||||
"The EU VAT Number extension functionality requires taxes be enabled on your "
|
||||
"store. To do so, go to %1$sWooCommerce > Settings%2$s, check the Enable tax "
|
||||
"rates and calculations checkbox, and click the Save changes button."
|
||||
msgstr ""
|
||||
|
||||
#: woocommerce-eu-vat-number.php:325
|
||||
msgid "Settings"
|
||||
msgstr ""
|
||||
|
||||
#: woocommerce-eu-vat-number.php:274
|
||||
#: woocommerce-eu-vat-number.php:345
|
||||
msgid "View Plugin Documentation"
|
||||
msgstr ""
|
||||
|
||||
#: woocommerce-eu-vat-number.php:274
|
||||
#: woocommerce-eu-vat-number.php:345
|
||||
msgid "Docs"
|
||||
msgstr ""
|
||||
|
||||
#: woocommerce-eu-vat-number.php:280
|
||||
#: woocommerce-eu-vat-number.php:351
|
||||
msgid "View Plugin Changelog"
|
||||
msgstr ""
|
||||
|
||||
#: woocommerce-eu-vat-number.php:280
|
||||
#: woocommerce-eu-vat-number.php:351
|
||||
msgid "Changelog"
|
||||
msgstr ""
|
||||
|
||||
#: woocommerce-eu-vat-number.php:286
|
||||
#: woocommerce-eu-vat-number.php:357
|
||||
msgid "Support"
|
||||
msgstr ""
|
||||
|
||||
#: woocommerce-eu-vat-number.php:323
|
||||
#: woocommerce-eu-vat-number.php:394
|
||||
msgid "VAT Number"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -1,130 +1,130 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { sprintf, __ } from '@wordpress/i18n';
|
||||
import { useSelect } from '@wordpress/data';
|
||||
import { CheckboxControl } from '@woocommerce/blocks-checkout';
|
||||
import {
|
||||
useState,
|
||||
createInterpolateElement,
|
||||
useEffect,
|
||||
} from '@wordpress/element';
|
||||
import { getSetting } from '@woocommerce/settings';
|
||||
|
||||
/**
|
||||
* Renders a warning when the customer's IP address does not match the billing country they chose.
|
||||
*
|
||||
* @param {Object} props Incoming props for the component.
|
||||
* @param {boolean} props.shouldValidateIp Whether WC EU VAT Number is set up to validate the customer's IP address.
|
||||
* @param {string} props.billingCountry The customer's billing country.
|
||||
* @param {string} props.ipAddress The customer's IP address.
|
||||
* @param {string} props.ipCountry The country that the customer's IP is from.
|
||||
* @param {Object} props.validation Object containing WooCommerce Blocks validation methods.
|
||||
* @param {Object} props.checkoutExtensionData Object containing setCheckoutData to allow us to pass data to the checkout endpoint.
|
||||
* @return {JSX.Element|null} The component to render, or null if there's nothing to render.
|
||||
*/
|
||||
export const IpAddressNotice = ( {
|
||||
shouldValidateIp,
|
||||
billingCountry,
|
||||
ipAddress,
|
||||
ipCountry,
|
||||
validation,
|
||||
checkoutExtensionData,
|
||||
} ) => {
|
||||
const countryLocales = getSetting( 'allowedCountries', {} );
|
||||
const { setExtensionData } = checkoutExtensionData;
|
||||
let countryName = billingCountry;
|
||||
if ( !! countryLocales[ billingCountry ] ) {
|
||||
countryName = countryLocales[ billingCountry ];
|
||||
}
|
||||
const { extensions } = useSelect( ( select ) =>
|
||||
select( 'wc/store/cart' ).getCartData()
|
||||
);
|
||||
const { cart_has_digital_goods: cartHasDigitalGoods } =
|
||||
extensions[ 'woocommerce-eu-vat-number' ];
|
||||
|
||||
const { setValidationErrors, clearValidationError, getValidationError } =
|
||||
validation;
|
||||
|
||||
const [ isChecked, setIsChecked ] = useState( false );
|
||||
const [ isDirty, setIsDirty ] = useState( false );
|
||||
const validationErrorId = 'billing_vat_number_ip_address_notice';
|
||||
|
||||
const validationErrorMessage = sprintf(
|
||||
/* translators: %1$s is the user's IP address, %2$s is the billing country name */
|
||||
__(
|
||||
'Your IP Address (%1$s) does not match your billing country (%2$s). European VAT laws require your IP address to match your billing country when purchasing digital goods in the EU. Please confirm you are located within your billing country using the checkbox above.',
|
||||
'woocommerce-eu-vat-number'
|
||||
),
|
||||
ipAddress,
|
||||
countryName
|
||||
);
|
||||
|
||||
const isSelfDeclarationRequired =
|
||||
shouldValidateIp && cartHasDigitalGoods && billingCountry !== ipCountry;
|
||||
|
||||
useEffect( () => {
|
||||
if ( ! isChecked && isSelfDeclarationRequired ) {
|
||||
setValidationErrors( {
|
||||
[ validationErrorId ]: {
|
||||
message: validationErrorMessage,
|
||||
hidden: ! isDirty,
|
||||
},
|
||||
} );
|
||||
}
|
||||
if ( isChecked ) {
|
||||
clearValidationError( validationErrorId );
|
||||
}
|
||||
|
||||
// When unmounting we need to clear the error to allow checkout to continue.
|
||||
return () => {
|
||||
clearValidationError( validationErrorId );
|
||||
};
|
||||
}, [ setValidationErrors, isChecked, isDirty ] );
|
||||
|
||||
if ( ! isSelfDeclarationRequired ) {
|
||||
return null;
|
||||
}
|
||||
const validationError = getValidationError( validationErrorId );
|
||||
|
||||
return (
|
||||
<div className="wc-eu-vat-checkout-ip-notice">
|
||||
<div className="wc-eu-vat-checkout-ip-notice__checkbox-container">
|
||||
<CheckboxControl
|
||||
name={ 'location_confirmation' }
|
||||
className={
|
||||
validationError?.hidden === false ? 'has-error' : ''
|
||||
}
|
||||
label={ createInterpolateElement(
|
||||
sprintf(
|
||||
/* translators: %s is the billing country full name, e.g. Finland, France, or Spain. */
|
||||
__(
|
||||
'I am established, have my permanent address, or usually reside within <strong>%s</strong>.',
|
||||
'woocommerce-eu-vat-number'
|
||||
),
|
||||
countryName
|
||||
),
|
||||
{ strong: <strong /> }
|
||||
) }
|
||||
checked={ isChecked }
|
||||
onChange={ ( checked ) => {
|
||||
if ( ! isDirty ) {
|
||||
setIsDirty( true );
|
||||
}
|
||||
setIsChecked( checked );
|
||||
setExtensionData(
|
||||
'woocommerce-eu-vat-number',
|
||||
'location_confirmation',
|
||||
checked
|
||||
);
|
||||
} }
|
||||
/>
|
||||
</div>
|
||||
{ validationError?.message && ! validationError?.hidden ? (
|
||||
<div className="wc-eu-vat-checkout-ip-notice__error wc-block-components-validation-error">
|
||||
{ validationError.message }
|
||||
</div>
|
||||
) : null }
|
||||
</div>
|
||||
);
|
||||
};
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { sprintf, __ } from '@wordpress/i18n';
|
||||
import { useSelect } from '@wordpress/data';
|
||||
import { CheckboxControl } from '@woocommerce/blocks-checkout';
|
||||
import {
|
||||
useState,
|
||||
createInterpolateElement,
|
||||
useEffect,
|
||||
} from '@wordpress/element';
|
||||
import { getSetting } from '@woocommerce/settings';
|
||||
|
||||
/**
|
||||
* Renders a warning when the customer's IP address does not match the billing country they chose.
|
||||
*
|
||||
* @param {Object} props Incoming props for the component.
|
||||
* @param {boolean} props.shouldValidateIp Whether WC EU VAT Number is set up to validate the customer's IP address.
|
||||
* @param {string} props.billingCountry The customer's billing country.
|
||||
* @param {string} props.ipAddress The customer's IP address.
|
||||
* @param {string} props.ipCountry The country that the customer's IP is from.
|
||||
* @param {Object} props.validation Object containing WooCommerce Blocks validation methods.
|
||||
* @param {Object} props.checkoutExtensionData Object containing setCheckoutData to allow us to pass data to the checkout endpoint.
|
||||
* @return {JSX.Element|null} The component to render, or null if there's nothing to render.
|
||||
*/
|
||||
export const IpAddressNotice = ( {
|
||||
shouldValidateIp,
|
||||
billingCountry,
|
||||
ipAddress,
|
||||
ipCountry,
|
||||
validation,
|
||||
checkoutExtensionData,
|
||||
} ) => {
|
||||
const countryLocales = getSetting( 'allowedCountries', {} );
|
||||
const { setExtensionData } = checkoutExtensionData;
|
||||
let countryName = billingCountry;
|
||||
if ( !! countryLocales[ billingCountry ] ) {
|
||||
countryName = countryLocales[ billingCountry ];
|
||||
}
|
||||
const { extensions } = useSelect( ( select ) =>
|
||||
select( 'wc/store/cart' ).getCartData()
|
||||
);
|
||||
const { cart_has_digital_goods: cartHasDigitalGoods } =
|
||||
extensions[ 'woocommerce-eu-vat-number' ];
|
||||
|
||||
const { setValidationErrors, clearValidationError, getValidationError } =
|
||||
validation;
|
||||
|
||||
const [ isChecked, setIsChecked ] = useState( false );
|
||||
const [ isDirty, setIsDirty ] = useState( false );
|
||||
const validationErrorId = 'billing_vat_number_ip_address_notice';
|
||||
|
||||
const validationErrorMessage = sprintf(
|
||||
/* translators: %1$s is the user's IP address, %2$s is the billing country name */
|
||||
__(
|
||||
'Your IP Address (%1$s) does not match your billing country (%2$s). European VAT laws require your IP address to match your billing country when purchasing digital goods in the EU. Please confirm you are located within your billing country using the checkbox above.',
|
||||
'woocommerce-eu-vat-number'
|
||||
),
|
||||
ipAddress,
|
||||
countryName
|
||||
);
|
||||
|
||||
const isSelfDeclarationRequired =
|
||||
shouldValidateIp && cartHasDigitalGoods && billingCountry !== ipCountry;
|
||||
|
||||
useEffect( () => {
|
||||
if ( ! isChecked && isSelfDeclarationRequired ) {
|
||||
setValidationErrors( {
|
||||
[ validationErrorId ]: {
|
||||
message: validationErrorMessage,
|
||||
hidden: ! isDirty,
|
||||
},
|
||||
} );
|
||||
}
|
||||
if ( isChecked ) {
|
||||
clearValidationError( validationErrorId );
|
||||
}
|
||||
|
||||
// When unmounting we need to clear the error to allow checkout to continue.
|
||||
return () => {
|
||||
clearValidationError( validationErrorId );
|
||||
};
|
||||
}, [ setValidationErrors, isChecked, isDirty ] );
|
||||
|
||||
if ( ! isSelfDeclarationRequired ) {
|
||||
return null;
|
||||
}
|
||||
const validationError = getValidationError( validationErrorId );
|
||||
|
||||
return (
|
||||
<div className="wc-eu-vat-checkout-ip-notice">
|
||||
<div className="wc-eu-vat-checkout-ip-notice__checkbox-container">
|
||||
<CheckboxControl
|
||||
name={ 'location_confirmation' }
|
||||
className={
|
||||
validationError?.hidden === false ? 'has-error' : ''
|
||||
}
|
||||
label={ createInterpolateElement(
|
||||
sprintf(
|
||||
/* translators: %s is the billing country full name, e.g. Finland, France, or Spain. */
|
||||
__(
|
||||
'I am established, have my permanent address, or usually reside within <strong>%s</strong>.',
|
||||
'woocommerce-eu-vat-number'
|
||||
),
|
||||
countryName
|
||||
),
|
||||
{ strong: <strong /> }
|
||||
) }
|
||||
checked={ isChecked }
|
||||
onChange={ ( checked ) => {
|
||||
if ( ! isDirty ) {
|
||||
setIsDirty( true );
|
||||
}
|
||||
setIsChecked( checked );
|
||||
setExtensionData(
|
||||
'woocommerce-eu-vat-number',
|
||||
'location_confirmation',
|
||||
checked
|
||||
);
|
||||
} }
|
||||
/>
|
||||
</div>
|
||||
{ validationError?.message && ! validationError?.hidden ? (
|
||||
<div className="wc-eu-vat-checkout-ip-notice__error wc-block-components-validation-error">
|
||||
{ validationError.message }
|
||||
</div>
|
||||
) : null }
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,28 +1,28 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const attributes = ( {
|
||||
defaultTitle = __( 'Step', 'woocommerce-eu-vat-number' ),
|
||||
defaultDescription = __(
|
||||
'Step description text.',
|
||||
'woocommerce-eu-vat-number'
|
||||
),
|
||||
defaultShowStepNumber = true,
|
||||
} ) => ( {
|
||||
title: {
|
||||
type: 'string',
|
||||
default: defaultTitle,
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
default: defaultDescription,
|
||||
},
|
||||
showStepNumber: {
|
||||
type: 'boolean',
|
||||
default: defaultShowStepNumber,
|
||||
},
|
||||
} );
|
||||
|
||||
export default attributes;
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
const attributes = ( {
|
||||
defaultTitle = __( 'Step', 'woocommerce-eu-vat-number' ),
|
||||
defaultDescription = __(
|
||||
'Step description text.',
|
||||
'woocommerce-eu-vat-number'
|
||||
),
|
||||
defaultShowStepNumber = true,
|
||||
} ) => ( {
|
||||
title: {
|
||||
type: 'string',
|
||||
default: defaultTitle,
|
||||
},
|
||||
description: {
|
||||
type: 'string',
|
||||
default: defaultDescription,
|
||||
},
|
||||
showStepNumber: {
|
||||
type: 'boolean',
|
||||
default: defaultShowStepNumber,
|
||||
},
|
||||
} );
|
||||
|
||||
export default attributes;
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
|
||||
.wc-block-checkout__additional_fields {
|
||||
margin: 1.5em 0 0;
|
||||
}
|
||||
.wc-block-components-checkout-step__description-placeholder {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-step__title {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.wc-block-checkout__additional_fields {
|
||||
margin: 1.5em 0 0;
|
||||
}
|
||||
.wc-block-components-checkout-step__description-placeholder {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-step__title {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
}
|
||||
|
|
|
@ -1,91 +1,91 @@
|
|||
/* eslint-disable jsdoc/require-param */
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import classnames from 'classnames';
|
||||
import {
|
||||
PlainText,
|
||||
InspectorControls,
|
||||
useBlockProps,
|
||||
} from '@wordpress/block-editor';
|
||||
import { PanelBody, ToggleControl } from '@wordpress/components';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import FormStepHeading from './form-step-heading';
|
||||
|
||||
/**
|
||||
* Form Step Block for use in the editor.
|
||||
*/
|
||||
export const FormStepBlock = ( {
|
||||
attributes,
|
||||
setAttributes,
|
||||
className = '',
|
||||
children,
|
||||
} ) => {
|
||||
const { title = '', description = '', showStepNumber = true } = attributes;
|
||||
const blockProps = useBlockProps( {
|
||||
className: classnames( 'wc-block-components-checkout-step', className, {
|
||||
'wc-block-components-checkout-step--with-step-number':
|
||||
showStepNumber,
|
||||
} ),
|
||||
} );
|
||||
return (
|
||||
<div { ...blockProps }>
|
||||
<InspectorControls>
|
||||
<PanelBody
|
||||
title={ __(
|
||||
'Form Step Options',
|
||||
'woocommerce-eu-vat-number'
|
||||
) }
|
||||
>
|
||||
<ToggleControl
|
||||
label={ __(
|
||||
'Show step number',
|
||||
'woocommerce-eu-vat-number'
|
||||
) }
|
||||
checked={ showStepNumber }
|
||||
onChange={ () =>
|
||||
setAttributes( {
|
||||
showStepNumber: ! showStepNumber,
|
||||
} )
|
||||
}
|
||||
/>
|
||||
</PanelBody>
|
||||
</InspectorControls>
|
||||
<FormStepHeading>
|
||||
<PlainText
|
||||
className={ '' }
|
||||
value={ title }
|
||||
onChange={ ( value ) => setAttributes( { title: value } ) }
|
||||
/>
|
||||
</FormStepHeading>
|
||||
<div className="wc-block-components-checkout-step__container">
|
||||
<p className="wc-block-components-checkout-step__description">
|
||||
<PlainText
|
||||
className={
|
||||
! description
|
||||
? 'wc-block-components-checkout-step__description-placeholder'
|
||||
: ''
|
||||
}
|
||||
value={ description }
|
||||
placeholder={ __(
|
||||
'Optional text for this form step.',
|
||||
'woocommerce-eu-vat-number'
|
||||
) }
|
||||
onChange={ ( value ) =>
|
||||
setAttributes( {
|
||||
description: value,
|
||||
} )
|
||||
}
|
||||
/>
|
||||
</p>
|
||||
<div className="wc-block-components-checkout-step__content">
|
||||
{ children }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
/* eslint-disable jsdoc/require-param */
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import classnames from 'classnames';
|
||||
import {
|
||||
PlainText,
|
||||
InspectorControls,
|
||||
useBlockProps,
|
||||
} from '@wordpress/block-editor';
|
||||
import { PanelBody, ToggleControl } from '@wordpress/components';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import FormStepHeading from './form-step-heading';
|
||||
|
||||
/**
|
||||
* Form Step Block for use in the editor.
|
||||
*/
|
||||
export const FormStepBlock = ( {
|
||||
attributes,
|
||||
setAttributes,
|
||||
className = '',
|
||||
children,
|
||||
} ) => {
|
||||
const { title = '', description = '', showStepNumber = true } = attributes;
|
||||
const blockProps = useBlockProps( {
|
||||
className: classnames( 'wc-block-components-checkout-step', className, {
|
||||
'wc-block-components-checkout-step--with-step-number':
|
||||
showStepNumber,
|
||||
} ),
|
||||
} );
|
||||
return (
|
||||
<div { ...blockProps }>
|
||||
<InspectorControls>
|
||||
<PanelBody
|
||||
title={ __(
|
||||
'Form Step Options',
|
||||
'woocommerce-eu-vat-number'
|
||||
) }
|
||||
>
|
||||
<ToggleControl
|
||||
label={ __(
|
||||
'Show step number',
|
||||
'woocommerce-eu-vat-number'
|
||||
) }
|
||||
checked={ showStepNumber }
|
||||
onChange={ () =>
|
||||
setAttributes( {
|
||||
showStepNumber: ! showStepNumber,
|
||||
} )
|
||||
}
|
||||
/>
|
||||
</PanelBody>
|
||||
</InspectorControls>
|
||||
<FormStepHeading>
|
||||
<PlainText
|
||||
className={ '' }
|
||||
value={ title }
|
||||
onChange={ ( value ) => setAttributes( { title: value } ) }
|
||||
/>
|
||||
</FormStepHeading>
|
||||
<div className="wc-block-components-checkout-step__container">
|
||||
<p className="wc-block-components-checkout-step__description">
|
||||
<PlainText
|
||||
className={
|
||||
! description
|
||||
? 'wc-block-components-checkout-step__description-placeholder'
|
||||
: ''
|
||||
}
|
||||
value={ description }
|
||||
placeholder={ __(
|
||||
'Optional text for this form step.',
|
||||
'woocommerce-eu-vat-number'
|
||||
) }
|
||||
onChange={ ( value ) =>
|
||||
setAttributes( {
|
||||
description: value,
|
||||
} )
|
||||
}
|
||||
/>
|
||||
</p>
|
||||
<div className="wc-block-components-checkout-step__content">
|
||||
{ children }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
/* eslint-disable jsdoc/require-param */
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
|
||||
/**
|
||||
* Step Heading Component
|
||||
*/
|
||||
const FormStepHeading = ( { children, stepHeadingContent } ) => (
|
||||
<div className="wc-block-components-checkout-step__heading">
|
||||
<h2
|
||||
aria-hidden="true"
|
||||
className="wc-block-components-checkout-step__title wc-block-components-title"
|
||||
>
|
||||
{ children }
|
||||
</h2>
|
||||
{ !! stepHeadingContent && (
|
||||
<span className="wc-block-components-checkout-step__heading-content">
|
||||
{ stepHeadingContent }
|
||||
</span>
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
|
||||
export default FormStepHeading;
|
||||
/* eslint-disable jsdoc/require-param */
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
|
||||
/**
|
||||
* Step Heading Component
|
||||
*/
|
||||
const FormStepHeading = ( { children, stepHeadingContent } ) => (
|
||||
<div className="wc-block-components-checkout-step__heading">
|
||||
<h2
|
||||
aria-hidden="true"
|
||||
className="wc-block-components-checkout-step__title wc-block-components-title"
|
||||
>
|
||||
{ children }
|
||||
</h2>
|
||||
{ !! stepHeadingContent && (
|
||||
<span className="wc-block-components-checkout-step__heading-content">
|
||||
{ stepHeadingContent }
|
||||
</span>
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
|
||||
export default FormStepHeading;
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
export * from './attributes';
|
||||
export * from './form-step-block';
|
||||
export * from './form-step-heading';
|
||||
export * from './attributes';
|
||||
export * from './form-step-block';
|
||||
export * from './form-step-heading';
|
||||
|
|
|
@ -1,82 +1,82 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import classnames from 'classnames';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './style.scss';
|
||||
import { withFilteredAttributes } from '../../utils';
|
||||
import attributes from '../form-step-block/attributes';
|
||||
|
||||
const StepHeading = ( { title, stepHeadingContent } ) => (
|
||||
<div className="wc-block-components-checkout-step__heading">
|
||||
<h2
|
||||
aria-hidden="true"
|
||||
className="wc-block-components-checkout-step__title wc-block-components-title"
|
||||
>
|
||||
{ title }
|
||||
</h2>
|
||||
{ !! stepHeadingContent && (
|
||||
<span className="wc-block-components-checkout-step__heading-content">
|
||||
{ stepHeadingContent }
|
||||
</span>
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
const FormStep = ( {
|
||||
id,
|
||||
className,
|
||||
title,
|
||||
legend,
|
||||
description,
|
||||
children,
|
||||
disabled = false,
|
||||
showStepNumber = true,
|
||||
stepHeadingContent = () => undefined,
|
||||
} ) => {
|
||||
// If the form step doesn't have a legend or title, render a <div> instead
|
||||
// of a <fieldset>.
|
||||
const Element = legend || title ? 'fieldset' : 'div';
|
||||
|
||||
return (
|
||||
<Element
|
||||
className={ classnames(
|
||||
className,
|
||||
'wc-block-components-checkout-step',
|
||||
{
|
||||
'wc-block-components-checkout-step--with-step-number':
|
||||
showStepNumber,
|
||||
'wc-block-components-checkout-step--disabled': disabled,
|
||||
}
|
||||
) }
|
||||
id={ id }
|
||||
disabled={ disabled }
|
||||
>
|
||||
{ !! ( legend || title ) && (
|
||||
<legend className="screen-reader-text">
|
||||
{ legend || title }
|
||||
</legend>
|
||||
) }
|
||||
{ !! title && (
|
||||
<StepHeading
|
||||
title={ title }
|
||||
stepHeadingContent={ stepHeadingContent() }
|
||||
/>
|
||||
) }
|
||||
<div className="wc-block-components-checkout-step__container">
|
||||
{ !! description && (
|
||||
<p className="wc-block-components-checkout-step__description">
|
||||
{ description }
|
||||
</p>
|
||||
) }
|
||||
<div className="wc-block-components-checkout-step__content">
|
||||
{ children }
|
||||
</div>
|
||||
</div>
|
||||
</Element>
|
||||
);
|
||||
};
|
||||
|
||||
export default withFilteredAttributes( attributes( {} ) )( FormStep );
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import classnames from 'classnames';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './style.scss';
|
||||
import { withFilteredAttributes } from '../../utils';
|
||||
import attributes from '../form-step-block/attributes';
|
||||
|
||||
const StepHeading = ( { title, stepHeadingContent } ) => (
|
||||
<div className="wc-block-components-checkout-step__heading">
|
||||
<h2
|
||||
aria-hidden="true"
|
||||
className="wc-block-components-checkout-step__title wc-block-components-title"
|
||||
>
|
||||
{ title }
|
||||
</h2>
|
||||
{ !! stepHeadingContent && (
|
||||
<span className="wc-block-components-checkout-step__heading-content">
|
||||
{ stepHeadingContent }
|
||||
</span>
|
||||
) }
|
||||
</div>
|
||||
);
|
||||
const FormStep = ( {
|
||||
id,
|
||||
className,
|
||||
title,
|
||||
legend,
|
||||
description,
|
||||
children,
|
||||
disabled = false,
|
||||
showStepNumber = true,
|
||||
stepHeadingContent = () => undefined,
|
||||
} ) => {
|
||||
// If the form step doesn't have a legend or title, render a <div> instead
|
||||
// of a <fieldset>.
|
||||
const Element = legend || title ? 'fieldset' : 'div';
|
||||
|
||||
return (
|
||||
<Element
|
||||
className={ classnames(
|
||||
className,
|
||||
'wc-block-components-checkout-step',
|
||||
{
|
||||
'wc-block-components-checkout-step--with-step-number':
|
||||
showStepNumber,
|
||||
'wc-block-components-checkout-step--disabled': disabled,
|
||||
}
|
||||
) }
|
||||
id={ id }
|
||||
disabled={ disabled }
|
||||
>
|
||||
{ !! ( legend || title ) && (
|
||||
<legend className="screen-reader-text">
|
||||
{ legend || title }
|
||||
</legend>
|
||||
) }
|
||||
{ !! title && (
|
||||
<StepHeading
|
||||
title={ title }
|
||||
stepHeadingContent={ stepHeadingContent() }
|
||||
/>
|
||||
) }
|
||||
<div className="wc-block-components-checkout-step__container">
|
||||
{ !! description && (
|
||||
<p className="wc-block-components-checkout-step__description">
|
||||
{ description }
|
||||
</p>
|
||||
) }
|
||||
<div className="wc-block-components-checkout-step__content">
|
||||
{ children }
|
||||
</div>
|
||||
</div>
|
||||
</Element>
|
||||
);
|
||||
};
|
||||
|
||||
export default withFilteredAttributes( attributes( {} ) )( FormStep );
|
||||
|
|
|
@ -1,129 +1,129 @@
|
|||
.wc-block-components-form {
|
||||
counter-reset: checkout-step;
|
||||
}
|
||||
|
||||
.wc-block-components-form .wc-block-components-checkout-step {
|
||||
position: relative;
|
||||
border: none;
|
||||
padding: 0 0 0 $gap-large;
|
||||
background: none;
|
||||
margin: 0;
|
||||
|
||||
.is-mobile &,
|
||||
.is-small & {
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-step--disabled {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-step__container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-step__content > * {
|
||||
margin-bottom: em($gap);
|
||||
}
|
||||
.wc-block-components-checkout-step--with-step-number .wc-block-components-checkout-step__content > :last-child {
|
||||
margin-bottom: 0;
|
||||
padding-bottom: em($gap-large);
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-step__heading {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-content: center;
|
||||
flex-wrap: wrap;
|
||||
margin: em($gap-small) 0 em($gap);
|
||||
position: relative;
|
||||
align-items: center;
|
||||
gap: em($gap);
|
||||
|
||||
.wc-block-components-express-payment-continue-rule + .wc-block-components-checkout-step & {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-step:first-child .wc-block-components-checkout-step__heading {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-step__title {
|
||||
margin: 0 $gap-small 0 0;
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-step__heading-content {
|
||||
font-size: 0.75em;
|
||||
|
||||
a {
|
||||
font-weight: bold;
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-step__description {
|
||||
font-size: 0.875em;
|
||||
line-height: 1.25;
|
||||
margin-bottom: $gap;
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-step--with-step-number {
|
||||
.wc-block-components-checkout-step__title::before {
|
||||
@include reset-box();
|
||||
background: transparent;
|
||||
counter-increment: checkout-step;
|
||||
content: "\00a0" counter(checkout-step) ".";
|
||||
content: "\00a0" counter(checkout-step) "." / "";
|
||||
position: absolute;
|
||||
width: $gap-large;
|
||||
left: -$gap-large;
|
||||
top: 0;
|
||||
text-align: center;
|
||||
transform: translateX(-50%);
|
||||
|
||||
.is-mobile &,
|
||||
.is-small & {
|
||||
position: static;
|
||||
transform: none;
|
||||
left: auto;
|
||||
top: auto;
|
||||
content: counter(checkout-step) ".\00a0";
|
||||
content: counter(checkout-step) ".\00a0" / "";
|
||||
}
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-step__container::after {
|
||||
content: "";
|
||||
height: 100%;
|
||||
border-left: 1px solid;
|
||||
opacity: 0.3;
|
||||
position: absolute;
|
||||
left: -$gap-large;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.is-mobile &,
|
||||
.is-small & {
|
||||
.wc-block-components-checkout-step__title::before {
|
||||
position: static;
|
||||
transform: none;
|
||||
left: auto;
|
||||
top: auto;
|
||||
content: counter(checkout-step) ".\00a0";
|
||||
content: counter(checkout-step) ".\00a0" / "";
|
||||
}
|
||||
.wc-block-components-checkout-step__container::after {
|
||||
content: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.editor-styles-wrapper {
|
||||
.wp-block h4.wc-block-components-checkout-step__title {
|
||||
font-size: 1em;
|
||||
line-height: 24px;
|
||||
margin: 0 $gap-small 0 0;
|
||||
}
|
||||
}
|
||||
.wc-block-components-form {
|
||||
counter-reset: checkout-step;
|
||||
}
|
||||
|
||||
.wc-block-components-form .wc-block-components-checkout-step {
|
||||
position: relative;
|
||||
border: none;
|
||||
padding: 0 0 0 $gap-large;
|
||||
background: none;
|
||||
margin: 0;
|
||||
|
||||
.is-mobile &,
|
||||
.is-small & {
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-step--disabled {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-step__container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-step__content > * {
|
||||
margin-bottom: em($gap);
|
||||
}
|
||||
.wc-block-components-checkout-step--with-step-number .wc-block-components-checkout-step__content > :last-child {
|
||||
margin-bottom: 0;
|
||||
padding-bottom: em($gap-large);
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-step__heading {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-content: center;
|
||||
flex-wrap: wrap;
|
||||
margin: em($gap-small) 0 em($gap);
|
||||
position: relative;
|
||||
align-items: center;
|
||||
gap: em($gap);
|
||||
|
||||
.wc-block-components-express-payment-continue-rule + .wc-block-components-checkout-step & {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-step:first-child .wc-block-components-checkout-step__heading {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-step__title {
|
||||
margin: 0 $gap-small 0 0;
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-step__heading-content {
|
||||
font-size: 0.75em;
|
||||
|
||||
a {
|
||||
font-weight: bold;
|
||||
color: inherit;
|
||||
}
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-step__description {
|
||||
font-size: 0.875em;
|
||||
line-height: 1.25;
|
||||
margin-bottom: $gap;
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-step--with-step-number {
|
||||
.wc-block-components-checkout-step__title::before {
|
||||
@include reset-box();
|
||||
background: transparent;
|
||||
counter-increment: checkout-step;
|
||||
content: "\00a0" counter(checkout-step) ".";
|
||||
content: "\00a0" counter(checkout-step) "." / "";
|
||||
position: absolute;
|
||||
width: $gap-large;
|
||||
left: -$gap-large;
|
||||
top: 0;
|
||||
text-align: center;
|
||||
transform: translateX(-50%);
|
||||
|
||||
.is-mobile &,
|
||||
.is-small & {
|
||||
position: static;
|
||||
transform: none;
|
||||
left: auto;
|
||||
top: auto;
|
||||
content: counter(checkout-step) ".\00a0";
|
||||
content: counter(checkout-step) ".\00a0" / "";
|
||||
}
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-step__container::after {
|
||||
content: "";
|
||||
height: 100%;
|
||||
border-left: 1px solid;
|
||||
opacity: 0.3;
|
||||
position: absolute;
|
||||
left: -$gap-large;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.is-mobile &,
|
||||
.is-small & {
|
||||
.wc-block-components-checkout-step__title::before {
|
||||
position: static;
|
||||
transform: none;
|
||||
left: auto;
|
||||
top: auto;
|
||||
content: counter(checkout-step) ".\00a0";
|
||||
content: counter(checkout-step) ".\00a0" / "";
|
||||
}
|
||||
.wc-block-components-checkout-step__container::after {
|
||||
content: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.editor-styles-wrapper {
|
||||
.wp-block h4.wc-block-components-checkout-step__title {
|
||||
font-size: 1em;
|
||||
line-height: 24px;
|
||||
margin: 0 $gap-small 0 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,323 +1,323 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { useState, useEffect } from '@wordpress/element';
|
||||
|
||||
import { withInstanceId } from '@wordpress/compose';
|
||||
import { extensionCartUpdate } from '@woocommerce/blocks-checkout';
|
||||
import { getSetting } from '@woocommerce/settings';
|
||||
import classnames from 'classnames';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { useStoreCart } from '../../hooks';
|
||||
import { validateCountryVatNumberFormat } from '../../utils';
|
||||
import { IpAddressNotice } from '../IpAddressNotice';
|
||||
import FormStep from '../form-step';
|
||||
|
||||
const VatInput = ( props ) => {
|
||||
const { setValidationErrors, clearValidationError, getValidationError } =
|
||||
props.validation;
|
||||
const { checkoutExtensionData } = props;
|
||||
|
||||
const { billingAddress, extensions } = useStoreCart();
|
||||
const {
|
||||
b2b_required,
|
||||
eu_countries,
|
||||
uk_ni_notice,
|
||||
input_label,
|
||||
input_description,
|
||||
failure_handler,
|
||||
} = wc_eu_vat_params;
|
||||
|
||||
const {
|
||||
title = __( 'VAT Number', 'woocommerce-eu-vat-number' ),
|
||||
description = '',
|
||||
showStepNumber = true,
|
||||
} = props;
|
||||
|
||||
const {
|
||||
woocommerce_eu_vat_number_validate_ip,
|
||||
ip_address: ipAddress,
|
||||
ip_country: ipCountry,
|
||||
} = getSetting( 'woocommerce-eu-vat-number_data' );
|
||||
const shouldValidateIp = woocommerce_eu_vat_number_validate_ip === 'yes';
|
||||
|
||||
const [ isActive, setIsActive ] = useState( false );
|
||||
const [ vat, setVat ] = useState(
|
||||
extensions[ 'woocommerce-eu-vat-number' ]?.vat_number
|
||||
);
|
||||
const [ previousVat, setPreviousVat ] = useState(
|
||||
extensions[ 'woocommerce-eu-vat-number' ]?.vat_number
|
||||
);
|
||||
const [ required ] = useState(
|
||||
b2b_required === 'yes' &&
|
||||
eu_countries.indexOf( billingAddress.country ) !== -1
|
||||
);
|
||||
const [ available, setAvailable ] = useState(
|
||||
eu_countries.indexOf( billingAddress.country ) !== -1
|
||||
);
|
||||
const [ showGBNotice, setShowGBNotice ] = useState(
|
||||
billingAddress.country === 'GB'
|
||||
);
|
||||
|
||||
const textInputId = 'billing_vat_number';
|
||||
const validationErrorId = 'billing_vat_number_error';
|
||||
const className = 'eu-vat-extra-css';
|
||||
|
||||
const error = getValidationError( validationErrorId );
|
||||
const hasError = error?.hidden === false && error?.message !== '';
|
||||
|
||||
/**
|
||||
* This effect sets location_confirmation, it is required regardless of shouldValidateIp, or else the API will give
|
||||
* us an error due to missing parameters.
|
||||
*/
|
||||
useEffect( () => {
|
||||
checkoutExtensionData.setExtensionData(
|
||||
'woocommerce-eu-vat-number',
|
||||
'location_confirmation',
|
||||
false
|
||||
);
|
||||
}, [ checkoutExtensionData.setExtensionData ] );
|
||||
|
||||
/**
|
||||
* On country change, check if the country is in the EU, if not then set the VAT Input to not available.
|
||||
* Also update whether the GB Notice should show.
|
||||
*/
|
||||
useEffect( () => {
|
||||
setAvailable( eu_countries.indexOf( billingAddress.country ) !== -1 );
|
||||
setShowGBNotice( billingAddress.country === 'GB' );
|
||||
}, [ eu_countries, billingAddress.country ] );
|
||||
|
||||
/**
|
||||
* This effect handles setting the validation error immediately.
|
||||
*/
|
||||
useEffect( () => {
|
||||
if ( ! required || ( typeof vat === 'string' && vat.length > 0 ) ) {
|
||||
return;
|
||||
}
|
||||
// Instantly set the validation error when loading the component to ensure submissions without touching the
|
||||
// field cause an error to show when submitting. It is hidden at first because we don't want to show the error
|
||||
// until the user has touched the field.
|
||||
setValidationErrors( {
|
||||
[ validationErrorId ]: {
|
||||
message: __(
|
||||
'VAT number is required.',
|
||||
'woocommerce-eu-vat-number'
|
||||
),
|
||||
hidden: true,
|
||||
},
|
||||
} );
|
||||
}, [ required, setValidationErrors, validationErrorId ] );
|
||||
|
||||
const verifyVat = () => {
|
||||
if ( vat === previousVat ) {
|
||||
return;
|
||||
}
|
||||
clearValidationError( validationErrorId );
|
||||
// If required is true,and vat is null, undefined, or an empty string.
|
||||
if (
|
||||
required &&
|
||||
( vat === null ||
|
||||
typeof vat === 'undefined' ||
|
||||
( typeof vat === 'string' && vat.length === 0 ) )
|
||||
) {
|
||||
setValidationErrors( {
|
||||
[ validationErrorId ]: {
|
||||
message: __(
|
||||
'VAT number is required.',
|
||||
'woocommerce-eu-vat-number'
|
||||
),
|
||||
hidden: false,
|
||||
},
|
||||
} );
|
||||
}
|
||||
extensionCartUpdate( {
|
||||
namespace: 'woocommerce-eu-vat-number',
|
||||
data: {
|
||||
vat_number: vat,
|
||||
},
|
||||
cartPropsToReceive: [ 'extensions' ],
|
||||
} ).then( () => {
|
||||
setPreviousVat( vat );
|
||||
// If we get here and VAT is empty and not required then remove the error message. This is because an empty
|
||||
// VAT Number still causes an erorr when we try to update the server, but we need to update the server
|
||||
// to tell it the VAT Number is empty...
|
||||
if ( ! required && ! vat ) {
|
||||
clearValidationError( validationErrorId );
|
||||
}
|
||||
} );
|
||||
};
|
||||
|
||||
const init = () => {
|
||||
if (
|
||||
typeof vat === 'string' &&
|
||||
vat.length > 0 &&
|
||||
( ( ! validateCountryVatNumberFormat(
|
||||
billingAddress.country,
|
||||
vat
|
||||
) &&
|
||||
failure_handler === 'reject' ) ||
|
||||
( ! extensions[ 'woocommerce-eu-vat-number' ]?.validation
|
||||
?.valid &&
|
||||
vat ===
|
||||
extensions[ 'woocommerce-eu-vat-number' ]?.vat_number &&
|
||||
failure_handler === 'reject' ) )
|
||||
) {
|
||||
setValidationErrors( {
|
||||
[ validationErrorId ]: {
|
||||
message:
|
||||
extensions[ 'woocommerce-eu-vat-number' ]?.validation
|
||||
.error,
|
||||
hidden: false,
|
||||
},
|
||||
} );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This effect runs when extensions[ 'woocommerce-eu-vat-number' ]?.validation.error changes. We can set the error
|
||||
* on the front-end based on this, or clear it if it's empty.
|
||||
*/
|
||||
useEffect( () => {
|
||||
// If vat number is empty AND this is the first render, skip showing the error. The error will have hidden: true
|
||||
// if it's the first render. Subsequent interactions will unhide the error if the state is invalid.
|
||||
// If vat is not empty, then the state can be considered 'dirty' and we continue to show the error.
|
||||
const validationError = getValidationError( validationErrorId );
|
||||
if ( ! vat && validationError?.hidden ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! required && ! vat ) {
|
||||
clearValidationError( validationErrorId );
|
||||
return;
|
||||
}
|
||||
if ( extensions[ 'woocommerce-eu-vat-number' ]?.validation?.error ) {
|
||||
setValidationErrors( {
|
||||
[ validationErrorId ]: {
|
||||
message:
|
||||
extensions[ 'woocommerce-eu-vat-number' ]?.validation
|
||||
.error,
|
||||
hidden: false,
|
||||
},
|
||||
} );
|
||||
return;
|
||||
}
|
||||
clearValidationError( validationErrorId );
|
||||
}, [ extensions[ 'woocommerce-eu-vat-number' ]?.validation.error ] );
|
||||
|
||||
/**
|
||||
* This effect kicks off the init function when the component mounts for the first time.
|
||||
*/
|
||||
useEffect( init, [] );
|
||||
|
||||
const onChange = ( event ) => {
|
||||
const { value: nextValue } = event.target;
|
||||
clearValidationError( validationErrorId );
|
||||
if (
|
||||
typeof nextValue === 'string' &&
|
||||
nextValue.length === 0 &&
|
||||
required
|
||||
) {
|
||||
setValidationErrors( {
|
||||
[ validationErrorId ]: {
|
||||
message: __(
|
||||
'VAT Number is required.',
|
||||
'woocommerce-eu-vat-number'
|
||||
),
|
||||
hidden: false,
|
||||
},
|
||||
} );
|
||||
}
|
||||
setVat( nextValue );
|
||||
};
|
||||
|
||||
const HasError = () => {
|
||||
if ( ! hasError ) return null;
|
||||
return (
|
||||
<div className="wc-block-components-validation-error" role="alert">
|
||||
<p id={ validationErrorId }>
|
||||
{ getValidationError( validationErrorId )?.message }
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
if ( ! available ) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
return (
|
||||
<FormStep
|
||||
id="shipping-fields"
|
||||
className={ classnames(
|
||||
'wc-block-checkout__shipping-fields',
|
||||
className
|
||||
) }
|
||||
title={ title }
|
||||
description={ description }
|
||||
showStepNumber={ showStepNumber }
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
className={ classnames(
|
||||
'wc-block-components-text-input',
|
||||
className,
|
||||
{
|
||||
'is-active': isActive || !! vat,
|
||||
},
|
||||
{
|
||||
'has-error': hasError,
|
||||
}
|
||||
) }
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
// eslint-disable-next-line camelcase
|
||||
aria-label={ input_label }
|
||||
id={ textInputId }
|
||||
value={ vat || '' }
|
||||
onChange={ ( event ) => {
|
||||
onChange( event );
|
||||
} }
|
||||
onFocus={ () => setIsActive( true ) }
|
||||
onBlur={ () => {
|
||||
setIsActive( false );
|
||||
verifyVat();
|
||||
} }
|
||||
aria-invalid={ hasError === true }
|
||||
disabled={ false }
|
||||
required={ required }
|
||||
/>
|
||||
|
||||
<label htmlFor={ textInputId }>
|
||||
{ input_label }
|
||||
{ required === true ? null : ' (optional)' }
|
||||
</label>
|
||||
<HasError />
|
||||
<div className="wc-eu-vat-checkout-uk-notice">
|
||||
<div>
|
||||
<span>{ input_description }</span>
|
||||
</div>
|
||||
<span>{ showGBNotice ? uk_ni_notice : null }</span>
|
||||
</div>
|
||||
</div>
|
||||
{ ( ! vat && b2b_required === 'no' ) ||
|
||||
( ! vat && ! b2b_required ) ? (
|
||||
<IpAddressNotice
|
||||
validation={ props.validation }
|
||||
ipAddress={ ipAddress }
|
||||
ipCountry={ ipCountry }
|
||||
billingCountry={ billingAddress.country }
|
||||
shouldValidateIp={ shouldValidateIp }
|
||||
checkoutExtensionData={ checkoutExtensionData }
|
||||
/>
|
||||
) : null }
|
||||
</div>
|
||||
</FormStep>
|
||||
);
|
||||
};
|
||||
|
||||
export default withInstanceId( VatInput );
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { useState, useEffect } from '@wordpress/element';
|
||||
|
||||
import { withInstanceId } from '@wordpress/compose';
|
||||
import { extensionCartUpdate } from '@woocommerce/blocks-checkout';
|
||||
import { getSetting } from '@woocommerce/settings';
|
||||
import classnames from 'classnames';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { useStoreCart } from '../../hooks';
|
||||
import { validateCountryVatNumberFormat } from '../../utils';
|
||||
import { IpAddressNotice } from '../IpAddressNotice';
|
||||
import FormStep from '../form-step';
|
||||
|
||||
const VatInput = ( props ) => {
|
||||
const { setValidationErrors, clearValidationError, getValidationError } =
|
||||
props.validation;
|
||||
const { checkoutExtensionData } = props;
|
||||
|
||||
const { billingAddress, extensions } = useStoreCart();
|
||||
const {
|
||||
b2b_required,
|
||||
eu_countries,
|
||||
uk_ni_notice,
|
||||
input_label,
|
||||
input_description,
|
||||
failure_handler,
|
||||
} = wc_eu_vat_params;
|
||||
|
||||
const {
|
||||
title = __( 'VAT Number', 'woocommerce-eu-vat-number' ),
|
||||
description = '',
|
||||
showStepNumber = true,
|
||||
} = props;
|
||||
|
||||
const {
|
||||
woocommerce_eu_vat_number_validate_ip,
|
||||
ip_address: ipAddress,
|
||||
ip_country: ipCountry,
|
||||
} = getSetting( 'woocommerce-eu-vat-number_data' );
|
||||
const shouldValidateIp = woocommerce_eu_vat_number_validate_ip === 'yes';
|
||||
|
||||
const [ isActive, setIsActive ] = useState( false );
|
||||
const [ vat, setVat ] = useState(
|
||||
extensions[ 'woocommerce-eu-vat-number' ]?.vat_number
|
||||
);
|
||||
const [ previousVat, setPreviousVat ] = useState(
|
||||
extensions[ 'woocommerce-eu-vat-number' ]?.vat_number
|
||||
);
|
||||
const [ required ] = useState(
|
||||
b2b_required === 'yes' &&
|
||||
eu_countries.indexOf( billingAddress.country ) !== -1
|
||||
);
|
||||
const [ available, setAvailable ] = useState(
|
||||
eu_countries.indexOf( billingAddress.country ) !== -1
|
||||
);
|
||||
const [ showGBNotice, setShowGBNotice ] = useState(
|
||||
billingAddress.country === 'GB'
|
||||
);
|
||||
|
||||
const textInputId = 'billing_vat_number';
|
||||
const validationErrorId = 'billing_vat_number_error';
|
||||
const className = 'eu-vat-extra-css';
|
||||
|
||||
const error = getValidationError( validationErrorId );
|
||||
const hasError = error?.hidden === false && error?.message !== '';
|
||||
|
||||
/**
|
||||
* This effect sets location_confirmation, it is required regardless of shouldValidateIp, or else the API will give
|
||||
* us an error due to missing parameters.
|
||||
*/
|
||||
useEffect( () => {
|
||||
checkoutExtensionData.setExtensionData(
|
||||
'woocommerce-eu-vat-number',
|
||||
'location_confirmation',
|
||||
false
|
||||
);
|
||||
}, [ checkoutExtensionData.setExtensionData ] );
|
||||
|
||||
/**
|
||||
* On country change, check if the country is in the EU, if not then set the VAT Input to not available.
|
||||
* Also update whether the GB Notice should show.
|
||||
*/
|
||||
useEffect( () => {
|
||||
setAvailable( eu_countries.indexOf( billingAddress.country ) !== -1 );
|
||||
setShowGBNotice( billingAddress.country === 'GB' );
|
||||
}, [ eu_countries, billingAddress.country ] );
|
||||
|
||||
/**
|
||||
* This effect handles setting the validation error immediately.
|
||||
*/
|
||||
useEffect( () => {
|
||||
if ( ! required || ( typeof vat === 'string' && vat.length > 0 ) ) {
|
||||
return;
|
||||
}
|
||||
// Instantly set the validation error when loading the component to ensure submissions without touching the
|
||||
// field cause an error to show when submitting. It is hidden at first because we don't want to show the error
|
||||
// until the user has touched the field.
|
||||
setValidationErrors( {
|
||||
[ validationErrorId ]: {
|
||||
message: __(
|
||||
'VAT number is required.',
|
||||
'woocommerce-eu-vat-number'
|
||||
),
|
||||
hidden: true,
|
||||
},
|
||||
} );
|
||||
}, [ required, setValidationErrors, validationErrorId ] );
|
||||
|
||||
const verifyVat = () => {
|
||||
if ( vat === previousVat ) {
|
||||
return;
|
||||
}
|
||||
clearValidationError( validationErrorId );
|
||||
// If required is true,and vat is null, undefined, or an empty string.
|
||||
if (
|
||||
required &&
|
||||
( vat === null ||
|
||||
typeof vat === 'undefined' ||
|
||||
( typeof vat === 'string' && vat.length === 0 ) )
|
||||
) {
|
||||
setValidationErrors( {
|
||||
[ validationErrorId ]: {
|
||||
message: __(
|
||||
'VAT number is required.',
|
||||
'woocommerce-eu-vat-number'
|
||||
),
|
||||
hidden: false,
|
||||
},
|
||||
} );
|
||||
}
|
||||
extensionCartUpdate( {
|
||||
namespace: 'woocommerce-eu-vat-number',
|
||||
data: {
|
||||
vat_number: vat,
|
||||
},
|
||||
cartPropsToReceive: [ 'extensions' ],
|
||||
} ).then( () => {
|
||||
setPreviousVat( vat );
|
||||
// If we get here and VAT is empty and not required then remove the error message. This is because an empty
|
||||
// VAT Number still causes an erorr when we try to update the server, but we need to update the server
|
||||
// to tell it the VAT Number is empty...
|
||||
if ( ! required && ! vat ) {
|
||||
clearValidationError( validationErrorId );
|
||||
}
|
||||
} );
|
||||
};
|
||||
|
||||
const init = () => {
|
||||
if (
|
||||
typeof vat === 'string' &&
|
||||
vat.length > 0 &&
|
||||
( ( ! validateCountryVatNumberFormat(
|
||||
billingAddress.country,
|
||||
vat
|
||||
) &&
|
||||
failure_handler === 'reject' ) ||
|
||||
( ! extensions[ 'woocommerce-eu-vat-number' ]?.validation
|
||||
?.valid &&
|
||||
vat ===
|
||||
extensions[ 'woocommerce-eu-vat-number' ]?.vat_number &&
|
||||
failure_handler === 'reject' ) )
|
||||
) {
|
||||
setValidationErrors( {
|
||||
[ validationErrorId ]: {
|
||||
message:
|
||||
extensions[ 'woocommerce-eu-vat-number' ]?.validation
|
||||
.error,
|
||||
hidden: false,
|
||||
},
|
||||
} );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* This effect runs when extensions[ 'woocommerce-eu-vat-number' ]?.validation.error changes. We can set the error
|
||||
* on the front-end based on this, or clear it if it's empty.
|
||||
*/
|
||||
useEffect( () => {
|
||||
// If vat number is empty AND this is the first render, skip showing the error. The error will have hidden: true
|
||||
// if it's the first render. Subsequent interactions will unhide the error if the state is invalid.
|
||||
// If vat is not empty, then the state can be considered 'dirty' and we continue to show the error.
|
||||
const validationError = getValidationError( validationErrorId );
|
||||
if ( ! vat && validationError?.hidden ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! required && ! vat ) {
|
||||
clearValidationError( validationErrorId );
|
||||
return;
|
||||
}
|
||||
if ( extensions[ 'woocommerce-eu-vat-number' ]?.validation?.error ) {
|
||||
setValidationErrors( {
|
||||
[ validationErrorId ]: {
|
||||
message:
|
||||
extensions[ 'woocommerce-eu-vat-number' ]?.validation
|
||||
.error,
|
||||
hidden: false,
|
||||
},
|
||||
} );
|
||||
return;
|
||||
}
|
||||
clearValidationError( validationErrorId );
|
||||
}, [ extensions[ 'woocommerce-eu-vat-number' ]?.validation.error ] );
|
||||
|
||||
/**
|
||||
* This effect kicks off the init function when the component mounts for the first time.
|
||||
*/
|
||||
useEffect( init, [] );
|
||||
|
||||
const onChange = ( event ) => {
|
||||
const { value: nextValue } = event.target;
|
||||
clearValidationError( validationErrorId );
|
||||
if (
|
||||
typeof nextValue === 'string' &&
|
||||
nextValue.length === 0 &&
|
||||
required
|
||||
) {
|
||||
setValidationErrors( {
|
||||
[ validationErrorId ]: {
|
||||
message: __(
|
||||
'VAT Number is required.',
|
||||
'woocommerce-eu-vat-number'
|
||||
),
|
||||
hidden: false,
|
||||
},
|
||||
} );
|
||||
}
|
||||
setVat( nextValue );
|
||||
};
|
||||
|
||||
const HasError = () => {
|
||||
if ( ! hasError ) return null;
|
||||
return (
|
||||
<div className="wc-block-components-validation-error" role="alert">
|
||||
<p id={ validationErrorId }>
|
||||
{ getValidationError( validationErrorId )?.message }
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
if ( ! available ) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
return (
|
||||
<FormStep
|
||||
id="shipping-fields"
|
||||
className={ classnames(
|
||||
'wc-block-checkout__shipping-fields',
|
||||
className
|
||||
) }
|
||||
title={ title }
|
||||
description={ description }
|
||||
showStepNumber={ showStepNumber }
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
className={ classnames(
|
||||
'wc-block-components-text-input',
|
||||
className,
|
||||
{
|
||||
'is-active': isActive || !! vat,
|
||||
},
|
||||
{
|
||||
'has-error': hasError,
|
||||
}
|
||||
) }
|
||||
>
|
||||
<input
|
||||
type="text"
|
||||
// eslint-disable-next-line camelcase
|
||||
aria-label={ input_label }
|
||||
id={ textInputId }
|
||||
value={ vat || '' }
|
||||
onChange={ ( event ) => {
|
||||
onChange( event );
|
||||
} }
|
||||
onFocus={ () => setIsActive( true ) }
|
||||
onBlur={ () => {
|
||||
setIsActive( false );
|
||||
verifyVat();
|
||||
} }
|
||||
aria-invalid={ hasError === true }
|
||||
disabled={ false }
|
||||
required={ required }
|
||||
/>
|
||||
|
||||
<label htmlFor={ textInputId }>
|
||||
{ input_label }
|
||||
{ required === true ? null : ' (optional)' }
|
||||
</label>
|
||||
<HasError />
|
||||
<div className="wc-eu-vat-checkout-uk-notice">
|
||||
<div>
|
||||
<span>{ input_description }</span>
|
||||
</div>
|
||||
<span>{ showGBNotice ? uk_ni_notice : null }</span>
|
||||
</div>
|
||||
</div>
|
||||
{ ( ! vat && b2b_required === 'no' ) ||
|
||||
( ! vat && ! b2b_required ) ? (
|
||||
<IpAddressNotice
|
||||
validation={ props.validation }
|
||||
ipAddress={ ipAddress }
|
||||
ipCountry={ ipCountry }
|
||||
billingCountry={ billingAddress.country }
|
||||
shouldValidateIp={ shouldValidateIp }
|
||||
checkoutExtensionData={ checkoutExtensionData }
|
||||
/>
|
||||
) : null }
|
||||
</div>
|
||||
</FormStep>
|
||||
);
|
||||
};
|
||||
|
||||
export default withInstanceId( VatInput );
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
@mixin reset-typography() {
|
||||
color: inherit;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
font-style: inherit;
|
||||
font-weight: inherit;
|
||||
letter-spacing: inherit;
|
||||
line-height: inherit;
|
||||
text-decoration: inherit;
|
||||
text-transform: inherit;
|
||||
}
|
||||
|
||||
// Converts a px unit to em.
|
||||
@function em($size, $base: 16px) {
|
||||
@return calc($size / $base) * 1em;
|
||||
}
|
||||
@mixin reset-box() {
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
@mixin reset-typography() {
|
||||
color: inherit;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
font-style: inherit;
|
||||
font-weight: inherit;
|
||||
letter-spacing: inherit;
|
||||
line-height: inherit;
|
||||
text-decoration: inherit;
|
||||
text-transform: inherit;
|
||||
}
|
||||
|
||||
// Converts a px unit to em.
|
||||
@function em($size, $base: 16px) {
|
||||
@return calc($size / $base) * 1em;
|
||||
}
|
||||
@mixin reset-box() {
|
||||
border: 0;
|
||||
border-radius: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
$gap-largest : 48px;
|
||||
$gap-large : 24px;
|
||||
$gap : 16px;
|
||||
$gap-small : 12px;
|
||||
$gap-largest : 48px;
|
||||
$gap-large : 24px;
|
||||
$gap : 16px;
|
||||
$gap-small : 12px;
|
||||
$gap-smallest: 4px;
|
|
@ -1,31 +1,31 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { registerCheckoutBlock } from '@woocommerce/blocks-checkout';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import blockMetadata from '../block.json';
|
||||
import VatInput from './components/vat-input';
|
||||
import formStepAttributes from './components/form-step-block/attributes';
|
||||
|
||||
const options = {
|
||||
metadata: {
|
||||
...blockMetadata,
|
||||
attributes: {
|
||||
...blockMetadata.attributes,
|
||||
...formStepAttributes( {
|
||||
defaultTitle: __( 'VAT Number', 'woocommerce-eu-vat-number' ),
|
||||
defaultDescription: '',
|
||||
defaultShowStepNumber: true,
|
||||
} ),
|
||||
},
|
||||
},
|
||||
component: ( props ) => {
|
||||
return <VatInput isEditing={ false } { ...props } />;
|
||||
},
|
||||
};
|
||||
|
||||
registerCheckoutBlock( options );
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { registerCheckoutBlock } from '@woocommerce/blocks-checkout';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import blockMetadata from '../block.json';
|
||||
import VatInput from './components/vat-input';
|
||||
import formStepAttributes from './components/form-step-block/attributes';
|
||||
|
||||
const options = {
|
||||
metadata: {
|
||||
...blockMetadata,
|
||||
attributes: {
|
||||
...blockMetadata.attributes,
|
||||
...formStepAttributes( {
|
||||
defaultTitle: __( 'VAT Number', 'woocommerce-eu-vat-number' ),
|
||||
defaultDescription: '',
|
||||
defaultShowStepNumber: true,
|
||||
} ),
|
||||
},
|
||||
},
|
||||
component: ( props ) => {
|
||||
return <VatInput isEditing={ false } { ...props } />;
|
||||
},
|
||||
};
|
||||
|
||||
registerCheckoutBlock( options );
|
||||
|
|
42
src/hooks.js
42
src/hooks.js
|
@ -1,21 +1,21 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { useSelect } from '@wordpress/data';
|
||||
|
||||
export const useStoreCart = () => {
|
||||
const CART_STORE_KEY = 'wc/store/cart';
|
||||
|
||||
const results = useSelect( ( select ) => {
|
||||
const store = select( CART_STORE_KEY );
|
||||
const cartData = store.getCartData();
|
||||
return {
|
||||
cartItems: cartData.items,
|
||||
billingAddress: cartData.billingAddress,
|
||||
extensions: cartData.extensions,
|
||||
needsShipping: cartData.needsShipping,
|
||||
};
|
||||
} );
|
||||
|
||||
return results;
|
||||
};
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { useSelect } from '@wordpress/data';
|
||||
|
||||
export const useStoreCart = () => {
|
||||
const CART_STORE_KEY = 'wc/store/cart';
|
||||
|
||||
const results = useSelect( ( select ) => {
|
||||
const store = select( CART_STORE_KEY );
|
||||
const cartData = store.getCartData();
|
||||
return {
|
||||
cartItems: cartData.items,
|
||||
billingAddress: cartData.billingAddress,
|
||||
extensions: cartData.extensions,
|
||||
needsShipping: cartData.needsShipping,
|
||||
};
|
||||
} );
|
||||
|
||||
return results;
|
||||
};
|
||||
|
|
124
src/index.js
124
src/index.js
|
@ -1,62 +1,62 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { registerBlockType } from '@wordpress/blocks';
|
||||
import { useBlockProps, InnerBlocks } from '@wordpress/block-editor';
|
||||
import classnames from 'classnames';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './index.scss';
|
||||
import block from '../block.json';
|
||||
import { FormStepBlock } from './components/form-step-block';
|
||||
import formStepAttributes from './components/form-step-block/attributes';
|
||||
|
||||
const Edit = ( props ) => {
|
||||
const blockProps = useBlockProps();
|
||||
return (
|
||||
<div { ...blockProps }>
|
||||
<FormStepBlock
|
||||
attributes={ props.attributes }
|
||||
setAttributes={ props.setAttributes }
|
||||
className={ classnames(
|
||||
'wc-block-checkout__vat-input',
|
||||
props.attributes?.className
|
||||
) }
|
||||
>
|
||||
<div className="wc-block-components-text-input">
|
||||
<input
|
||||
type="text"
|
||||
aria-label="VAT Number"
|
||||
id="woocommerce-eu-vat-number"
|
||||
/>
|
||||
<label htmlFor="woocommerce-eu-vat-number">
|
||||
{ __( 'VAT Number', 'woocommerce-eu-vat-number' ) }
|
||||
</label>
|
||||
</div>
|
||||
</FormStepBlock>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
const Save = () => {
|
||||
return (
|
||||
<div { ...useBlockProps.save() }>
|
||||
<InnerBlocks.Content />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
registerBlockType( block, {
|
||||
edit: Edit,
|
||||
attributes: {
|
||||
...block.attributes,
|
||||
...formStepAttributes( {
|
||||
defaultTitle: __( 'VAT Number', 'woocommerce-eu-vat-number' ),
|
||||
defaultDescription: '',
|
||||
defaultShowStepNumber: true,
|
||||
} ),
|
||||
},
|
||||
save: Save,
|
||||
} );
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { registerBlockType } from '@wordpress/blocks';
|
||||
import { useBlockProps, InnerBlocks } from '@wordpress/block-editor';
|
||||
import classnames from 'classnames';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import './index.scss';
|
||||
import block from '../block.json';
|
||||
import { FormStepBlock } from './components/form-step-block';
|
||||
import formStepAttributes from './components/form-step-block/attributes';
|
||||
|
||||
const Edit = ( props ) => {
|
||||
const blockProps = useBlockProps();
|
||||
return (
|
||||
<div { ...blockProps }>
|
||||
<FormStepBlock
|
||||
attributes={ props.attributes }
|
||||
setAttributes={ props.setAttributes }
|
||||
className={ classnames(
|
||||
'wc-block-checkout__vat-input',
|
||||
props.attributes?.className
|
||||
) }
|
||||
>
|
||||
<div className="wc-block-components-text-input">
|
||||
<input
|
||||
type="text"
|
||||
aria-label="VAT Number"
|
||||
id="woocommerce-eu-vat-number"
|
||||
/>
|
||||
<label htmlFor="woocommerce-eu-vat-number">
|
||||
{ __( 'VAT Number', 'woocommerce-eu-vat-number' ) }
|
||||
</label>
|
||||
</div>
|
||||
</FormStepBlock>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
const Save = () => {
|
||||
return (
|
||||
<div { ...useBlockProps.save() }>
|
||||
<InnerBlocks.Content />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
registerBlockType( block, {
|
||||
edit: Edit,
|
||||
attributes: {
|
||||
...block.attributes,
|
||||
...formStepAttributes( {
|
||||
defaultTitle: __( 'VAT Number', 'woocommerce-eu-vat-number' ),
|
||||
defaultDescription: '',
|
||||
defaultShowStepNumber: true,
|
||||
} ),
|
||||
},
|
||||
save: Save,
|
||||
} );
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
.wc-eu-vat-checkout-uk-notice {
|
||||
padding-top: 10px;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.eu-vat-extra-css > input {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.wc-eu-vat-checkout-ip-notice {
|
||||
|
||||
.wc-eu-vat-checkout-ip-notice__error {
|
||||
margin-top: 1em;
|
||||
}
|
||||
}
|
||||
.wc-eu-vat-checkout-uk-notice {
|
||||
padding-top: 10px;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.eu-vat-extra-css > input {
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.wc-eu-vat-checkout-ip-notice {
|
||||
|
||||
.wc-eu-vat-checkout-ip-notice__error {
|
||||
margin-top: 1em;
|
||||
}
|
||||
}
|
||||
|
|
196
src/utils.js
196
src/utils.js
|
@ -1,98 +1,98 @@
|
|||
export const validateCountryVatNumberFormat = ( country, vatNumber ) => {
|
||||
const regexExpressions = {
|
||||
AT: 'U[A-Z\\d]{8}',
|
||||
BE: '0\\d{9}',
|
||||
BG: '\\d{9,10}',
|
||||
CY: '\\d{8}[A-Z]',
|
||||
CZ: '\\d{8,10}',
|
||||
DE: '\\d{9}',
|
||||
DK: '(\\d{2} ?){3}\\d{2}',
|
||||
EE: '\\d{9}',
|
||||
EL: '\\d{9}',
|
||||
ES: '[A-Z]\\d{7}[A-Z]|\\d{8}[A-Z]|[A-Z]\\d{8}',
|
||||
FI: '\\d{8}',
|
||||
FR: '([A-Z]{2}|[A-Z0-9]{2})\\d{9}',
|
||||
XI: '\\d{9}|\\d{12}|(GD|HA)\\d{3}',
|
||||
HR: '\\d{11}',
|
||||
HU: '\\d{8}',
|
||||
IE: '[A-Z\\d]{8,10}',
|
||||
IT: '\\d{11}',
|
||||
LT: '(\\d{9}|\\d{12})',
|
||||
LU: '\\d{8}',
|
||||
LV: '\\d{11}',
|
||||
MT: '\\d{8}',
|
||||
NL: '\\d{9}B\\d{2}',
|
||||
PL: '\\d{10}',
|
||||
PT: '\\d{9}',
|
||||
RO: '\\d{2,10}',
|
||||
SE: '\\d{12}',
|
||||
SI: '\\d{8}',
|
||||
SK: '\\d{10}',
|
||||
};
|
||||
|
||||
if ( regexExpressions[ country ] ) {
|
||||
const regex = new RegExp( regexExpressions[ country ] );
|
||||
const match = regex.exec( vatNumber );
|
||||
return match !== null;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Given some block attributes, gets attributes from the dataset or uses defaults.
|
||||
*
|
||||
* @param {Object} blockAttributes Object containing block attributes.
|
||||
* @param {Array} rawAttributes Dataset from DOM.
|
||||
* @return {Array} Array of parsed attributes.
|
||||
*/
|
||||
export const getValidBlockAttributes = ( blockAttributes, rawAttributes ) => {
|
||||
const attributes = [];
|
||||
|
||||
Object.keys( blockAttributes ).forEach( ( key ) => {
|
||||
if ( typeof rawAttributes[ key ] !== 'undefined' ) {
|
||||
switch ( blockAttributes[ key ].type ) {
|
||||
case 'boolean':
|
||||
attributes[ key ] =
|
||||
rawAttributes[ key ] !== 'false' &&
|
||||
rawAttributes[ key ] !== false;
|
||||
break;
|
||||
case 'number':
|
||||
attributes[ key ] = parseInt( rawAttributes[ key ], 10 );
|
||||
break;
|
||||
case 'array':
|
||||
case 'object':
|
||||
attributes[ key ] = JSON.parse( rawAttributes[ key ] );
|
||||
break;
|
||||
default:
|
||||
attributes[ key ] = rawAttributes[ key ];
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
attributes[ key ] = blockAttributes[ key ].default;
|
||||
}
|
||||
} );
|
||||
|
||||
return attributes;
|
||||
};
|
||||
|
||||
/**
|
||||
* HOC that filters given attributes by valid block attribute values, or uses defaults if undefined.
|
||||
*
|
||||
* @param {Object} blockAttributes Component being wrapped.
|
||||
*/
|
||||
export const withFilteredAttributes =
|
||||
( blockAttributes ) => ( OriginalComponent ) => {
|
||||
return ( ownProps ) => {
|
||||
const validBlockAttributes = getValidBlockAttributes(
|
||||
blockAttributes,
|
||||
ownProps
|
||||
);
|
||||
|
||||
return (
|
||||
<OriginalComponent
|
||||
{ ...ownProps }
|
||||
{ ...validBlockAttributes }
|
||||
/>
|
||||
);
|
||||
};
|
||||
};
|
||||
export const validateCountryVatNumberFormat = ( country, vatNumber ) => {
|
||||
const regexExpressions = {
|
||||
AT: 'U[A-Z\\d]{8}',
|
||||
BE: '0\\d{9}',
|
||||
BG: '\\d{9,10}',
|
||||
CY: '\\d{8}[A-Z]',
|
||||
CZ: '\\d{8,10}',
|
||||
DE: '\\d{9}',
|
||||
DK: '(\\d{2} ?){3}\\d{2}',
|
||||
EE: '\\d{9}',
|
||||
EL: '\\d{9}',
|
||||
ES: '[A-Z]\\d{7}[A-Z]|\\d{8}[A-Z]|[A-Z]\\d{8}',
|
||||
FI: '\\d{8}',
|
||||
FR: '([A-Z]{2}|[A-Z0-9]{2})\\d{9}',
|
||||
XI: '\\d{9}|\\d{12}|(GD|HA)\\d{3}',
|
||||
HR: '\\d{11}',
|
||||
HU: '\\d{8}',
|
||||
IE: '[A-Z\\d]{8,10}',
|
||||
IT: '\\d{11}',
|
||||
LT: '(\\d{9}|\\d{12})',
|
||||
LU: '\\d{8}',
|
||||
LV: '\\d{11}',
|
||||
MT: '\\d{8}',
|
||||
NL: '\\d{9}B\\d{2}',
|
||||
PL: '\\d{10}',
|
||||
PT: '\\d{9}',
|
||||
RO: '\\d{2,10}',
|
||||
SE: '\\d{12}',
|
||||
SI: '\\d{8}',
|
||||
SK: '\\d{10}',
|
||||
};
|
||||
|
||||
if ( regexExpressions[ country ] ) {
|
||||
const regex = new RegExp( regexExpressions[ country ] );
|
||||
const match = regex.exec( vatNumber );
|
||||
return match !== null;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Given some block attributes, gets attributes from the dataset or uses defaults.
|
||||
*
|
||||
* @param {Object} blockAttributes Object containing block attributes.
|
||||
* @param {Array} rawAttributes Dataset from DOM.
|
||||
* @return {Array} Array of parsed attributes.
|
||||
*/
|
||||
export const getValidBlockAttributes = ( blockAttributes, rawAttributes ) => {
|
||||
const attributes = [];
|
||||
|
||||
Object.keys( blockAttributes ).forEach( ( key ) => {
|
||||
if ( typeof rawAttributes[ key ] !== 'undefined' ) {
|
||||
switch ( blockAttributes[ key ].type ) {
|
||||
case 'boolean':
|
||||
attributes[ key ] =
|
||||
rawAttributes[ key ] !== 'false' &&
|
||||
rawAttributes[ key ] !== false;
|
||||
break;
|
||||
case 'number':
|
||||
attributes[ key ] = parseInt( rawAttributes[ key ], 10 );
|
||||
break;
|
||||
case 'array':
|
||||
case 'object':
|
||||
attributes[ key ] = JSON.parse( rawAttributes[ key ] );
|
||||
break;
|
||||
default:
|
||||
attributes[ key ] = rawAttributes[ key ];
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
attributes[ key ] = blockAttributes[ key ].default;
|
||||
}
|
||||
} );
|
||||
|
||||
return attributes;
|
||||
};
|
||||
|
||||
/**
|
||||
* HOC that filters given attributes by valid block attribute values, or uses defaults if undefined.
|
||||
*
|
||||
* @param {Object} blockAttributes Component being wrapped.
|
||||
*/
|
||||
export const withFilteredAttributes =
|
||||
( blockAttributes ) => ( OriginalComponent ) => {
|
||||
return ( ownProps ) => {
|
||||
const validBlockAttributes = getValidBlockAttributes(
|
||||
blockAttributes,
|
||||
ownProps
|
||||
);
|
||||
|
||||
return (
|
||||
<OriginalComponent
|
||||
{ ...ownProps }
|
||||
{ ...validBlockAttributes }
|
||||
/>
|
||||
);
|
||||
};
|
||||
};
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
<?php
|
||||
/**
|
||||
* Location confirmation field template.
|
||||
*
|
||||
* @package woocommerce-eu-vat-number/templates
|
||||
* @since 2.2.0
|
||||
*/
|
||||
|
||||
?>
|
||||
<p class="form-row location_confirmation terms">
|
||||
<label for="location_confirmation" class="checkbox"><input type="checkbox" class="input-checkbox" name="location_confirmation" <?php checked( $location_confirmation_is_checked, true ); ?> id="location_confirmation" /> <span>
|
||||
<?php
|
||||
$billing_country = is_callable( array( WC()->customer, 'get_billing_country' ) ) ? WC()->customer->get_billing_country() : WC()->customer->get_country();
|
||||
/* translators: %s billing country */
|
||||
echo wp_kses_post( sprintf( __( 'I am established, have my permanent address, or usually reside within <strong>%s</strong>.', 'woocommerce-eu-vat-number' ), $countries[ $billing_country ] ) );
|
||||
?>
|
||||
</span>
|
||||
</label>
|
||||
</p>
|
||||
<?php
|
||||
/**
|
||||
* Location confirmation field template.
|
||||
*
|
||||
* @package woocommerce-eu-vat-number/templates
|
||||
* @since 2.2.0
|
||||
*/
|
||||
|
||||
?>
|
||||
<p class="form-row location_confirmation terms">
|
||||
<label for="location_confirmation" class="checkbox"><input type="checkbox" class="input-checkbox" name="location_confirmation" <?php checked( $location_confirmation_is_checked, true ); ?> id="location_confirmation" /> <span>
|
||||
<?php
|
||||
$billing_country = is_callable( array( WC()->customer, 'get_billing_country' ) ) ? WC()->customer->get_billing_country() : WC()->customer->get_country();
|
||||
/* translators: %s billing country */
|
||||
echo wp_kses_post( sprintf( __( 'I am established, have my permanent address, or usually reside within <strong>%s</strong>.', 'woocommerce-eu-vat-number' ), $countries[ $billing_country ] ) );
|
||||
?>
|
||||
</span>
|
||||
</label>
|
||||
</p>
|
||||
|
|
|
@ -1,29 +1,29 @@
|
|||
<?php
|
||||
/**
|
||||
* My Vat Number
|
||||
*
|
||||
* @package woocommerce-eu-vat-number/templates
|
||||
* @version 2.2.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
|
||||
<?php if ( ! empty( $messages ) ) { ?>
|
||||
<ul class="woocommerce-<?php echo esc_attr( $messages['status'] ); ?>">
|
||||
<li><?php echo wp_kses_post( $messages['message'] ); ?></li>
|
||||
</ul>
|
||||
<?php } ?>
|
||||
<form method="post">
|
||||
<p class="form-row form-row form-row-first">
|
||||
<input type="text" value="<?php echo esc_attr( $vat_number ); ?>" id="vat_number" name="vat_number" class="input-text" />
|
||||
</p>
|
||||
<div class="clear"></div>
|
||||
<p>
|
||||
<input type="submit" value="<?php echo esc_attr( __( 'Save', 'woocommerce-eu-vat-number' ) ); ?>" class="button" />
|
||||
<?php wp_nonce_field( 'woocommerce-edit_vat_number' ); ?>
|
||||
<input type="hidden" name="action" value="edit_vat_number" />
|
||||
</p>
|
||||
</form>
|
||||
<?php
|
||||
/**
|
||||
* My Vat Number
|
||||
*
|
||||
* @package woocommerce-eu-vat-number/templates
|
||||
* @version 2.2.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
|
||||
<?php if ( ! empty( $messages ) ) { ?>
|
||||
<ul class="woocommerce-<?php echo esc_attr( $messages['status'] ); ?>">
|
||||
<li><?php echo wp_kses_post( $messages['message'] ); ?></li>
|
||||
</ul>
|
||||
<?php } ?>
|
||||
<form method="post">
|
||||
<p class="form-row form-row form-row-first">
|
||||
<input type="text" value="<?php echo esc_attr( $vat_number ); ?>" id="vat_number" name="vat_number" class="input-text" />
|
||||
</p>
|
||||
<div class="clear"></div>
|
||||
<p>
|
||||
<input type="submit" value="<?php echo esc_attr( __( 'Save', 'woocommerce-eu-vat-number' ) ); ?>" class="button" />
|
||||
<?php wp_nonce_field( 'woocommerce-edit_vat_number' ); ?>
|
||||
<input type="hidden" name="action" value="edit_vat_number" />
|
||||
</p>
|
||||
</form>
|
||||
|
|
|
@ -1,349 +1,420 @@
|
|||
<?php
|
||||
/**
|
||||
* Plugin Name: WooCommerce EU VAT Number
|
||||
* Plugin URI: https://woocommerce.com/products/eu-vat-number/
|
||||
* Description: The EU VAT Number extension lets you collect and validate EU VAT numbers during checkout to identify B2B transactions verses B2C. IP Addresses can also be validated to ensure they match the billing address. EU businesses with a valid VAT number can have their VAT removed prior to payment.
|
||||
* Version: 2.8.3
|
||||
* Author: WooCommerce
|
||||
* Author URI: https://woocommerce.com/
|
||||
* Text Domain: woocommerce-eu-vat-number
|
||||
* Domain Path: /languages
|
||||
* Requires at least: 5.6
|
||||
* Tested up to: 6.1
|
||||
* WC requires at least: 6.8
|
||||
* WC tested up to: 7.4
|
||||
* Requires PHP: 7.2
|
||||
*
|
||||
<?php
|
||||
/**
|
||||
* Plugin Name: WooCommerce EU VAT Number
|
||||
* Plugin URI: https://woocommerce.com/products/eu-vat-number/
|
||||
* Description: The EU VAT Number extension lets you collect and validate EU VAT numbers during checkout to identify B2B transactions verses B2C. IP Addresses can also be validated to ensure they match the billing address. EU businesses with a valid VAT number can have their VAT removed prior to payment.
|
||||
* Version: 2.8.8
|
||||
* Author: WooCommerce
|
||||
* Author URI: https://woocommerce.com/
|
||||
* Text Domain: woocommerce-eu-vat-number
|
||||
* Domain Path: /languages
|
||||
* Requires at least: 6.1
|
||||
* Tested up to: 6.3
|
||||
* WC requires at least: 7.7
|
||||
* WC tested up to: 7.9
|
||||
* Requires PHP: 7.3
|
||||
*
|
||||
* Copyright: © 2023 WooCommerce
|
||||
* License: GNU General Public License v3.0
|
||||
* License URI: http://www.gnu.org/licenses/gpl-3.0.html
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
* Woo: 18592:d2720c4b4bb8d6908e530355b7a2d734
|
||||
*/
|
||||
|
||||
// phpcs:disable WordPress.Files.FileName
|
||||
|
||||
define( 'WC_EU_VAT_VERSION', '2.8.3' ); // WRCS: DEFINED_VERSION.
|
||||
define( 'WC_EU_VAT_FILE', __FILE__ );
|
||||
define( 'WC_EU_VAT_PLUGIN_URL', untrailingslashit( plugins_url( basename( plugin_dir_path( __FILE__ ) ), basename( __FILE__ ) ) ) );
|
||||
|
||||
/**
|
||||
* WC_EU_VAT_Number_Init class.
|
||||
*/
|
||||
class WC_EU_VAT_Number_Init {
|
||||
|
||||
/**
|
||||
* Min version of WooCommerce supported.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const WC_MIN_VERSION = '6.8';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
add_action( 'plugins_loaded', array( $this, 'init' ) );
|
||||
|
||||
add_action( 'plugins_loaded', array( $this, 'localization' ), 0 );
|
||||
|
||||
// Subscribe to automated translations.
|
||||
add_filter( 'woocommerce_translations_updates_for_' . basename( __FILE__, '.php' ), '__return_true' );
|
||||
|
||||
register_activation_hook( __FILE__, array( $this, 'install' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that WooCommerce is loaded before doing anything else.
|
||||
*
|
||||
* @return bool True if supported
|
||||
*/
|
||||
private function check_dependencies() {
|
||||
$dependencies = array(
|
||||
'wc_installed' => array(
|
||||
'callback' => array( $this, 'is_woocommerce_active' ),
|
||||
'notice_callback' => array( $this, 'woocommerce_inactive_notice' ),
|
||||
),
|
||||
'wc_minimum_version' => array(
|
||||
'callback' => array( $this, 'is_woocommerce_version_supported' ),
|
||||
'notice_callback' => array( $this, 'woocommerce_wrong_version_notice' ),
|
||||
),
|
||||
'soap_required' => array(
|
||||
'callback' => array( $this, 'is_soap_supported' ),
|
||||
'notice_callback' => array( $this, 'requires_soap_notice' ),
|
||||
),
|
||||
);
|
||||
foreach ( $dependencies as $check ) {
|
||||
if ( ! call_user_func( $check['callback'] ) ) {
|
||||
add_action( 'admin_notices', $check['notice_callback'] );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the WooCommerce plugin is active.
|
||||
* Note: Must be run after the "plugins_loaded" action fires.
|
||||
*
|
||||
* @since 1.0
|
||||
* @return bool
|
||||
*/
|
||||
public function is_woocommerce_active() {
|
||||
return class_exists( 'woocommerce' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current WooCommerce version is supported.
|
||||
* Note: Must be run after the "plugins_loaded" action fires.
|
||||
*
|
||||
* @since 1.0
|
||||
* @return bool
|
||||
*/
|
||||
public function is_woocommerce_version_supported() {
|
||||
return version_compare(
|
||||
get_option( 'woocommerce_db_version' ),
|
||||
self::WC_MIN_VERSION,
|
||||
'>='
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the WooCommerce Blocks is active.
|
||||
* Note: Must be run after the "plugins_loaded" action fires.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_woocommerce_blocks_active() {
|
||||
return class_exists( 'Automattic\WooCommerce\Blocks\Package' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current WooCommerce Blocks version is supported.
|
||||
* Note: Must be run after the "plugins_loaded" action fires.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_woocommerce_blocks_version_supported() {
|
||||
return version_compare(
|
||||
\Automattic\WooCommerce\Blocks\Package::get_version(),
|
||||
'7.3.0',
|
||||
'>='
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the server supports SOAP.
|
||||
*
|
||||
* @since 2.3.7
|
||||
* @return bool
|
||||
*/
|
||||
public function is_soap_supported() {
|
||||
return class_exists( 'SoapClient' );
|
||||
}
|
||||
|
||||
/**
|
||||
* WC inactive notice.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function woocommerce_inactive_notice() {
|
||||
if ( current_user_can( 'activate_plugins' ) ) {
|
||||
/* translators: %1$s: Plugin page link start %2$s Link end */
|
||||
echo '<div class="error"><p><strong>' . wp_kses_post( __( 'WooCommerce EU VAT Number is inactive.', 'woocommerce-eu-vat-number' ) . '</strong> ' . sprintf( __( 'The WooCommerce plugin must be active for EU VAT Number to work. %1$sPlease install and activate WooCommerce%2$s.', 'woocommerce-eu-vat-number' ), '<a href="' . esc_url( admin_url( 'plugins.php' ) ) . '">', '</a>' ) ) . '</p></div>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrong version notice.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function woocommerce_wrong_version_notice() {
|
||||
if ( current_user_can( 'activate_plugins' ) ) {
|
||||
/* translators: %1$s: Minimum version %2$s: Plugin page link start %3$s Link end */
|
||||
echo '<div class="error"><p><strong>' . wp_kses_post( __( 'WooCommerce EU VAT Number is inactive.', 'woocommerce-eu-vat-number' ) . '</strong> ' . sprintf( __( 'The WooCommerce plugin must be at least version %1$s for EU VAT Number to work. %2$sPlease upgrade WooCommerce%3$s.', 'woocommerce-eu-vat-number' ), self::WC_MIN_VERSION, '<a href="' . esc_url( admin_url( 'plugins.php' ) ) . '">', '</a>' ) ) . '</p></div>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* No SOAP support notice.
|
||||
*
|
||||
* @since 2.3.7
|
||||
*/
|
||||
public function requires_soap_notice() {
|
||||
if ( current_user_can( 'activate_plugins' ) ) {
|
||||
echo '<div class="error"><p><strong>' . esc_html__( 'WooCommerce EU VAT Number is inactive.', 'woocommerce-eu-vat-number' ) . '</strong> ' . esc_html__( 'Your server does not provide SOAP support which is required functionality for communicating with VIES. You will need to reach out to your web hosting provider to get information on how to enable this functionality on your server.', 'woocommerce-eu-vat-number' ) . '</p></div>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Init the plugin once WP is loaded.
|
||||
*/
|
||||
public function init() {
|
||||
if ( $this->check_dependencies() ) {
|
||||
if ( version_compare( get_option( 'woocommerce_eu_vat_version', 0 ), WC_EU_VAT_VERSION, '<' ) ) {
|
||||
add_action( 'init', array( $this, 'install' ) );
|
||||
}
|
||||
|
||||
include_once __DIR__ . '/includes/wc-eu-vat-functions.php';
|
||||
include_once __DIR__ . '/includes/class-wc-eu-vat-privacy.php';
|
||||
|
||||
if ( ! class_exists( 'WC_EU_VAT_Number' ) ) {
|
||||
include_once __DIR__ . '/includes/class-wc-eu-vat-number.php';
|
||||
include_once __DIR__ . '/includes/class-wc-eu-vat-my-account.php';
|
||||
}
|
||||
|
||||
if ( is_admin() ) {
|
||||
include_once __DIR__ . '/includes/class-wc-eu-vat-admin.php';
|
||||
include_once __DIR__ . '/includes/class-wc-eu-vat-reports.php';
|
||||
}
|
||||
|
||||
add_action( 'before_woocommerce_init', array( $this, 'declare_hpos_compatibility' ) );
|
||||
add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'plugin_action_links' ) );
|
||||
add_filter( 'plugin_row_meta', array( $this, 'plugin_row_meta' ), 10, 2 );
|
||||
add_filter( 'woocommerce_get_order_item_totals', 'wc_eu_vat_maybe_add_zero_tax_display', 10, 3 );
|
||||
add_action( 'init', array( $this, 'wc_eu_vat_number_block_init' ) );
|
||||
add_filter(
|
||||
'__experimental_woocommerce_blocks_add_data_attributes_to_block',
|
||||
function ( $allowed_blocks ) {
|
||||
if ( $this->is_woocommerce_blocks_active() && $this->is_woocommerce_blocks_version_supported() ) {
|
||||
$allowed_blocks[] = 'woocommerce/eu-vat-number';
|
||||
}
|
||||
return $allowed_blocks;
|
||||
},
|
||||
10,
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load translations.
|
||||
*/
|
||||
public function localization() {
|
||||
/**
|
||||
* Filters plugin locale.
|
||||
*
|
||||
* @since 2.1.11
|
||||
*/
|
||||
$locale = apply_filters( 'plugin_locale', get_locale(), 'woocommerce-eu-vat-number' );
|
||||
$dir = trailingslashit( WP_LANG_DIR );
|
||||
load_textdomain( 'woocommerce-eu-vat-number', $dir . 'woocommerce-eu-vat-number/woocommerce-eu-vat-number-' . $locale . '.mo' );
|
||||
load_plugin_textdomain( 'woocommerce-eu-vat-number', false, dirname( plugin_basename( WC_EU_VAT_FILE ) ) . '/languages' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Installer
|
||||
*/
|
||||
public function install() {
|
||||
update_option( 'woocommerce_eu_vat_version', WC_EU_VAT_VERSION );
|
||||
add_rewrite_endpoint( 'vat-number', EP_ROOT | EP_PAGES );
|
||||
flush_rewrite_rules();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add custom action links on the plugin screen.
|
||||
*
|
||||
* @param mixed $actions Plugin Actions Links.
|
||||
* @return array
|
||||
*/
|
||||
public function plugin_action_links( $actions ) {
|
||||
$custom_actions = array(
|
||||
'settings' => sprintf( '<a href="%s">%s</a>', admin_url( 'admin.php?page=wc-settings&tab=tax' ), __( 'Settings', 'woocommerce-eu-vat-number' ) ),
|
||||
);
|
||||
return array_merge( $custom_actions, $actions );
|
||||
}
|
||||
|
||||
/**
|
||||
* Show row meta on the plugin screen.
|
||||
*
|
||||
* @param mixed $links Plugin Row Meta.
|
||||
* @param mixed $file Plugin Base file.
|
||||
* @return array
|
||||
*/
|
||||
public function plugin_row_meta( $links, $file ) {
|
||||
if ( 'woocommerce-eu-vat-number/woocommerce-eu-vat-number.php' === $file ) {
|
||||
$row_meta = array(
|
||||
/**
|
||||
* Filters the plugin docs URL.
|
||||
*
|
||||
* @since 2.1.8
|
||||
*/
|
||||
'docs' => '<a href="' . esc_url( apply_filters( 'wc_eu_vat_number_docs_url', 'https://docs.woocommerce.com/document/eu-vat-number/' ) ) . '" title="' . esc_attr( __( 'View Plugin Documentation', 'woocommerce-eu-vat-number' ) ) . '">' . __( 'Docs', 'woocommerce-eu-vat-number' ) . '</a>',
|
||||
/**
|
||||
* Filters the plugin changelog URL.
|
||||
*
|
||||
* @since 2.1.8
|
||||
*/
|
||||
'changelog' => '<a href="' . esc_url( apply_filters( 'wc_eu_vat_number_changelog', 'https://woocommerce.com/changelogs/woocommerce-eu-vat-number/changelog.txt' ) ) . '" title="' . esc_attr( __( 'View Plugin Changelog', 'woocommerce-eu-vat-number' ) ) . '">' . __( 'Changelog', 'woocommerce-eu-vat-number' ) . '</a>',
|
||||
/**
|
||||
* Filters the plugin support URL.
|
||||
*
|
||||
* @since 2.1.8
|
||||
*/
|
||||
'support' => '<a href="' . esc_url( apply_filters( 'wc_eu_vat_number_support_url', 'https://woocommerce.com/my-account/create-a-ticket?select=18592' ) ) . '" title="' . esc_attr( __( 'Support', 'woocommerce-eu-vat-number' ) ) . '">' . __( 'Support', 'woocommerce-eu-vat-number' ) . '</a>',
|
||||
);
|
||||
return array_merge( $links, $row_meta );
|
||||
}
|
||||
return (array) $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers block type and registers with WC Blocks Integration Interface.
|
||||
*/
|
||||
public function wc_eu_vat_number_block_init() {
|
||||
if ( $this->is_woocommerce_blocks_active() && $this->is_woocommerce_blocks_version_supported() ) {
|
||||
include_once __DIR__ . '/includes/class-wc-eu-vat-blocks.php';
|
||||
add_action(
|
||||
'woocommerce_blocks_checkout_block_registration',
|
||||
function( $integration_registry ) {
|
||||
$integration_registry->register( new WC_EU_VAT_Blocks_Integration() );
|
||||
}
|
||||
);
|
||||
|
||||
if ( ! class_exists( 'WC_EU_VAT_Number' ) ) {
|
||||
include_once __DIR__ . '/includes/class-wc-eu-vat-number.php';
|
||||
include_once __DIR__ . '/includes/class-wc-eu-vat-my-account.php';
|
||||
}
|
||||
add_action(
|
||||
'wp_enqueue_scripts',
|
||||
function() {
|
||||
WC_EU_VAT_Number::localize_wc_eu_vat_params( 'wc-blocks-eu-vat-scripts-frontend' );
|
||||
}
|
||||
);
|
||||
|
||||
register_block_type(
|
||||
__DIR__ . '/block.json',
|
||||
array(
|
||||
'attributes' => array(
|
||||
'title' => array(
|
||||
'type' => 'string',
|
||||
'default' => __( 'VAT Number', 'woocommerce-eu-vat-number' ),
|
||||
),
|
||||
'description' => array(
|
||||
'type' => 'string',
|
||||
'default' => '',
|
||||
),
|
||||
'showStepNumber' => array(
|
||||
'type' => 'boolean',
|
||||
'default' => true,
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Declares support for HPOS.
|
||||
*/
|
||||
public function declare_hpos_compatibility() {
|
||||
if ( class_exists( '\Automattic\WooCommerce\Utilities\FeaturesUtil' ) ) {
|
||||
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
new WC_EU_VAT_Number_Init();
|
||||
* License: GNU General Public License v3.0
|
||||
* License URI: http://www.gnu.org/licenses/gpl-3.0.html
|
||||
*
|
||||
* @package woocommerce-eu-vat-number
|
||||
* Woo: 18592:d2720c4b4bb8d6908e530355b7a2d734
|
||||
*/
|
||||
|
||||
// phpcs:disable WordPress.Files.FileName
|
||||
|
||||
define( 'WC_EU_VAT_VERSION', '2.8.8' ); // WRCS: DEFINED_VERSION.
|
||||
define( 'WC_EU_VAT_FILE', __FILE__ );
|
||||
define( 'WC_EU_ABSPATH', __DIR__ . '/' );
|
||||
define( 'WC_EU_VAT_PLUGIN_URL', untrailingslashit( plugins_url( basename( plugin_dir_path( __FILE__ ) ), basename( __FILE__ ) ) ) );
|
||||
|
||||
/**
|
||||
* WC_EU_VAT_Number_Init class.
|
||||
*/
|
||||
class WC_EU_VAT_Number_Init {
|
||||
|
||||
/**
|
||||
* Min version of WooCommerce supported.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const WC_MIN_VERSION = '7.7';
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
public function __construct() {
|
||||
add_action( 'plugins_loaded', array( $this, 'init' ) );
|
||||
add_action( 'woocommerce_blocks_loaded', array( $this, 'wc_eu_vat_number_block_init' ) );
|
||||
|
||||
add_action( 'plugins_loaded', array( $this, 'localization' ), 0 );
|
||||
|
||||
// Subscribe to automated translations.
|
||||
add_filter( 'woocommerce_translations_updates_for_' . basename( __FILE__, '.php' ), '__return_true' );
|
||||
|
||||
register_activation_hook( __FILE__, array( $this, 'install' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that WooCommerce is loaded before doing anything else.
|
||||
*
|
||||
* @return bool True if supported
|
||||
*/
|
||||
private function check_dependencies() {
|
||||
$dependencies = array(
|
||||
'wc_installed' => array(
|
||||
'callback' => array( $this, 'is_woocommerce_active' ),
|
||||
'notice_callback' => array( $this, 'woocommerce_inactive_notice' ),
|
||||
),
|
||||
'wc_minimum_version' => array(
|
||||
'callback' => array( $this, 'is_woocommerce_version_supported' ),
|
||||
'notice_callback' => array( $this, 'woocommerce_wrong_version_notice' ),
|
||||
),
|
||||
'soap_required' => array(
|
||||
'callback' => array( $this, 'is_soap_supported' ),
|
||||
'notice_callback' => array( $this, 'requires_soap_notice' ),
|
||||
),
|
||||
'wc_tax_enabled' => array(
|
||||
'callback' => array( $this, 'is_taxes_enabled' ),
|
||||
'notice_callback' => array( $this, 'woocommerce_tax_disabled_notice' ),
|
||||
),
|
||||
);
|
||||
foreach ( $dependencies as $check ) {
|
||||
if ( ! call_user_func( $check['callback'] ) ) {
|
||||
add_action( 'admin_notices', $check['notice_callback'] );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the WooCommerce plugin is active.
|
||||
* Note: Must be run after the "plugins_loaded" action fires.
|
||||
*
|
||||
* @since 1.0
|
||||
* @return bool
|
||||
*/
|
||||
public function is_woocommerce_active() {
|
||||
return class_exists( 'woocommerce' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current WooCommerce version is supported.
|
||||
* Note: Must be run after the "plugins_loaded" action fires.
|
||||
*
|
||||
* @since 1.0
|
||||
* @return bool
|
||||
*/
|
||||
public function is_woocommerce_version_supported() {
|
||||
return version_compare(
|
||||
get_option( 'woocommerce_db_version' ),
|
||||
self::WC_MIN_VERSION,
|
||||
'>='
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the WooCommerce Blocks is active.
|
||||
* Note: Must be run after the "plugins_loaded" action fires.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_woocommerce_blocks_active() {
|
||||
return class_exists( 'Automattic\WooCommerce\Blocks\Package' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if WooCommerce taxes are enabled.
|
||||
*
|
||||
* @since 2.8.8
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_taxes_enabled() {
|
||||
return function_exists( 'wc_tax_enabled' ) && wc_tax_enabled();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current WooCommerce Blocks version is supported.
|
||||
* Note: Must be run after the "plugins_loaded" action fires.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function is_woocommerce_blocks_version_supported() {
|
||||
return version_compare(
|
||||
\Automattic\WooCommerce\Blocks\Package::get_version(),
|
||||
'7.3.0',
|
||||
'>='
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the server supports SOAP.
|
||||
*
|
||||
* @since 2.3.7
|
||||
* @return bool
|
||||
*/
|
||||
public function is_soap_supported() {
|
||||
return class_exists( 'SoapClient' );
|
||||
}
|
||||
|
||||
/**
|
||||
* WC inactive notice.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function woocommerce_inactive_notice() {
|
||||
if ( current_user_can( 'activate_plugins' ) ) {
|
||||
/* translators: %1$s: Plugin page link start %2$s Link end */
|
||||
echo '<div class="error"><p><strong>' . wp_kses_post( __( 'WooCommerce EU VAT Number is inactive.', 'woocommerce-eu-vat-number' ) . '</strong> ' . sprintf( __( 'The WooCommerce plugin must be active for EU VAT Number to work. %1$sPlease install and activate WooCommerce%2$s.', 'woocommerce-eu-vat-number' ), '<a href="' . esc_url( admin_url( 'plugins.php' ) ) . '">', '</a>' ) ) . '</p></div>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrong version notice.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
public function woocommerce_wrong_version_notice() {
|
||||
if ( current_user_can( 'activate_plugins' ) ) {
|
||||
/* translators: %1$s: Minimum version %2$s: Plugin page link start %3$s Link end */
|
||||
echo '<div class="error"><p><strong>' . wp_kses_post( __( 'WooCommerce EU VAT Number is inactive.', 'woocommerce-eu-vat-number' ) . '</strong> ' . sprintf( __( 'The WooCommerce plugin must be at least version %1$s for EU VAT Number to work. %2$sPlease upgrade WooCommerce%3$s.', 'woocommerce-eu-vat-number' ), self::WC_MIN_VERSION, '<a href="' . esc_url( admin_url( 'plugins.php' ) ) . '">', '</a>' ) ) . '</p></div>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* No SOAP support notice.
|
||||
*
|
||||
* @since 2.3.7
|
||||
*/
|
||||
public function requires_soap_notice() {
|
||||
if ( current_user_can( 'activate_plugins' ) ) {
|
||||
echo '<div class="error"><p><strong>' . esc_html__( 'WooCommerce EU VAT Number is inactive.', 'woocommerce-eu-vat-number' ) . '</strong> ' . esc_html__( 'Your server does not provide SOAP support which is required functionality for communicating with VIES. You will need to reach out to your web hosting provider to get information on how to enable this functionality on your server.', 'woocommerce-eu-vat-number' ) . '</p></div>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Taxes disabled notice.
|
||||
*
|
||||
* @since 2.8.8
|
||||
*/
|
||||
public function woocommerce_tax_disabled_notice() {
|
||||
if ( ! current_user_can( 'manage_woocommerce' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Recheck if the notice is needed.
|
||||
*
|
||||
* This is needed on the settings page as the options are updated after the
|
||||
* `init` hook fires. This means that the notice can be shown on the settings
|
||||
* page immediately after taxes are enabled and save is clicked.
|
||||
*/
|
||||
if ( $this->is_taxes_enabled() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Filters whether to show the tax disabled notice.
|
||||
*
|
||||
* This allows developers to prevent the taxes disabled notice from
|
||||
* being shown. In most cases it is recommended the extension be
|
||||
* deactivated if taxes are intentionally disabled.
|
||||
*
|
||||
* This hook is targeted at multisite set ups in which the extension is
|
||||
* globally enabled but individual sites may or may not need taxes to
|
||||
* be enabled.
|
||||
*
|
||||
* @since 2.8.8
|
||||
*
|
||||
* @param bool $show_notice Whether to show the notice.
|
||||
*/
|
||||
$show_notice = apply_filters( 'woocommerce_eu_vat_show_tax_disabled_notice', true );
|
||||
|
||||
if ( ! $show_notice ) {
|
||||
return;
|
||||
}
|
||||
|
||||
echo '<div class="error">';
|
||||
echo '<p><strong>' . esc_html__( 'WooCommerce EU VAT Number is inactive.', 'woocommerce-eu-vat-number' ) . '</strong> ';
|
||||
|
||||
printf(
|
||||
/* translators: %1$s: Settings link start %2$s: Link end */
|
||||
esc_html__( 'The EU VAT Number extension functionality requires taxes be enabled on your store. To do so, go to %1$sWooCommerce > Settings%2$s, check the Enable tax rates and calculations checkbox, and click the Save changes button.', 'woocommerce-eu-vat-number' ),
|
||||
'<a href="' . esc_url( admin_url( 'admin.php?page=wc-settings' ) ) . '">',
|
||||
'</a>'
|
||||
);
|
||||
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Init the plugin once WP is loaded.
|
||||
*/
|
||||
public function init() {
|
||||
if ( $this->check_dependencies() ) {
|
||||
if ( version_compare( get_option( 'woocommerce_eu_vat_version', 0 ), WC_EU_VAT_VERSION, '<' ) ) {
|
||||
add_action( 'init', array( $this, 'install' ) );
|
||||
}
|
||||
|
||||
include_once __DIR__ . '/includes/wc-eu-vat-functions.php';
|
||||
include_once __DIR__ . '/includes/class-wc-eu-vat-privacy.php';
|
||||
|
||||
if ( ! class_exists( 'WC_EU_VAT_Number' ) ) {
|
||||
include_once __DIR__ . '/includes/class-wc-eu-vat-number.php';
|
||||
include_once __DIR__ . '/includes/class-wc-eu-vat-my-account.php';
|
||||
}
|
||||
|
||||
if ( is_admin() ) {
|
||||
include_once __DIR__ . '/includes/class-wc-eu-vat-admin.php';
|
||||
include_once __DIR__ . '/includes/class-wc-eu-vat-reports.php';
|
||||
}
|
||||
|
||||
add_action( 'before_woocommerce_init', array( $this, 'declare_hpos_compatibility' ) );
|
||||
add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'plugin_action_links' ) );
|
||||
add_filter( 'plugin_row_meta', array( $this, 'plugin_row_meta' ), 10, 2 );
|
||||
add_filter( 'woocommerce_get_order_item_totals', 'wc_eu_vat_maybe_add_zero_tax_display', 10, 3 );
|
||||
add_filter(
|
||||
'__experimental_woocommerce_blocks_add_data_attributes_to_block',
|
||||
function ( $allowed_blocks ) {
|
||||
if ( $this->is_woocommerce_blocks_active() && $this->is_woocommerce_blocks_version_supported() ) {
|
||||
$allowed_blocks[] = 'woocommerce/eu-vat-number';
|
||||
}
|
||||
return $allowed_blocks;
|
||||
},
|
||||
10,
|
||||
1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load translations.
|
||||
*/
|
||||
public function localization() {
|
||||
/**
|
||||
* Filters plugin locale.
|
||||
*
|
||||
* @since 2.1.11
|
||||
*/
|
||||
$locale = apply_filters( 'plugin_locale', get_locale(), 'woocommerce-eu-vat-number' );
|
||||
$dir = trailingslashit( WP_LANG_DIR );
|
||||
load_textdomain( 'woocommerce-eu-vat-number', $dir . 'woocommerce-eu-vat-number/woocommerce-eu-vat-number-' . $locale . '.mo' );
|
||||
load_plugin_textdomain( 'woocommerce-eu-vat-number', false, dirname( plugin_basename( WC_EU_VAT_FILE ) ) . '/languages' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Installer
|
||||
*/
|
||||
public function install() {
|
||||
update_option( 'woocommerce_eu_vat_version', WC_EU_VAT_VERSION );
|
||||
add_rewrite_endpoint( 'vat-number', EP_ROOT | EP_PAGES );
|
||||
flush_rewrite_rules();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add custom action links on the plugin screen.
|
||||
*
|
||||
* @param mixed $actions Plugin Actions Links.
|
||||
* @return array
|
||||
*/
|
||||
public function plugin_action_links( $actions ) {
|
||||
$custom_actions = array(
|
||||
'settings' => sprintf( '<a href="%s">%s</a>', admin_url( 'admin.php?page=wc-settings&tab=tax' ), __( 'Settings', 'woocommerce-eu-vat-number' ) ),
|
||||
);
|
||||
return array_merge( $custom_actions, $actions );
|
||||
}
|
||||
|
||||
/**
|
||||
* Show row meta on the plugin screen.
|
||||
*
|
||||
* @param mixed $links Plugin Row Meta.
|
||||
* @param mixed $file Plugin Base file.
|
||||
* @return array
|
||||
*/
|
||||
public function plugin_row_meta( $links, $file ) {
|
||||
if ( 'woocommerce-eu-vat-number/woocommerce-eu-vat-number.php' === $file ) {
|
||||
$row_meta = array(
|
||||
/**
|
||||
* Filters the plugin docs URL.
|
||||
*
|
||||
* @since 2.1.8
|
||||
*/
|
||||
'docs' => '<a href="' . esc_url( apply_filters( 'wc_eu_vat_number_docs_url', 'https://docs.woocommerce.com/document/eu-vat-number/' ) ) . '" title="' . esc_attr( __( 'View Plugin Documentation', 'woocommerce-eu-vat-number' ) ) . '">' . __( 'Docs', 'woocommerce-eu-vat-number' ) . '</a>',
|
||||
/**
|
||||
* Filters the plugin changelog URL.
|
||||
*
|
||||
* @since 2.1.8
|
||||
*/
|
||||
'changelog' => '<a href="' . esc_url( apply_filters( 'wc_eu_vat_number_changelog', 'https://woocommerce.com/changelogs/woocommerce-eu-vat-number/changelog.txt' ) ) . '" title="' . esc_attr( __( 'View Plugin Changelog', 'woocommerce-eu-vat-number' ) ) . '">' . __( 'Changelog', 'woocommerce-eu-vat-number' ) . '</a>',
|
||||
/**
|
||||
* Filters the plugin support URL.
|
||||
*
|
||||
* @since 2.1.8
|
||||
*/
|
||||
'support' => '<a href="' . esc_url( apply_filters( 'wc_eu_vat_number_support_url', 'https://woocommerce.com/my-account/create-a-ticket?select=18592' ) ) . '" title="' . esc_attr( __( 'Support', 'woocommerce-eu-vat-number' ) ) . '">' . __( 'Support', 'woocommerce-eu-vat-number' ) . '</a>',
|
||||
);
|
||||
return array_merge( $links, $row_meta );
|
||||
}
|
||||
return (array) $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers block type and registers with WC Blocks Integration Interface.
|
||||
*/
|
||||
public function wc_eu_vat_number_block_init() {
|
||||
if ( $this->check_dependencies() && $this->is_woocommerce_blocks_active() && $this->is_woocommerce_blocks_version_supported() ) {
|
||||
include_once __DIR__ . '/includes/class-wc-eu-vat-blocks.php';
|
||||
add_action(
|
||||
'woocommerce_blocks_checkout_block_registration',
|
||||
function( $integration_registry ) {
|
||||
$integration_registry->register( new WC_EU_VAT_Blocks_Integration() );
|
||||
}
|
||||
);
|
||||
|
||||
if ( ! class_exists( 'WC_EU_VAT_Number' ) ) {
|
||||
include_once __DIR__ . '/includes/class-wc-eu-vat-number.php';
|
||||
include_once __DIR__ . '/includes/class-wc-eu-vat-my-account.php';
|
||||
}
|
||||
add_action(
|
||||
'wp_enqueue_scripts',
|
||||
function() {
|
||||
WC_EU_VAT_Number::localize_wc_eu_vat_params( 'wc-blocks-eu-vat-scripts-frontend' );
|
||||
}
|
||||
);
|
||||
|
||||
register_block_type(
|
||||
__DIR__ . '/block.json',
|
||||
array(
|
||||
'attributes' => array(
|
||||
'title' => array(
|
||||
'type' => 'string',
|
||||
'default' => __( 'VAT Number', 'woocommerce-eu-vat-number' ),
|
||||
),
|
||||
'description' => array(
|
||||
'type' => 'string',
|
||||
'default' => '',
|
||||
),
|
||||
'showStepNumber' => array(
|
||||
'type' => 'boolean',
|
||||
'default' => true,
|
||||
),
|
||||
),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Declares support for HPOS.
|
||||
*/
|
||||
public function declare_hpos_compatibility() {
|
||||
if ( class_exists( '\Automattic\WooCommerce\Utilities\FeaturesUtil' ) ) {
|
||||
\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', __FILE__, true );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
new WC_EU_VAT_Number_Init();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue