1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* Tax calculation and rate finding class. |
4
|
|
|
* |
5
|
|
|
*/ |
6
|
|
|
|
7
|
|
|
defined( 'ABSPATH' ) || exit; |
8
|
|
|
|
9
|
|
|
class WPInv_EUVat { |
10
|
|
|
|
11
|
|
|
/** |
12
|
|
|
* Retrieves an instance of this class. |
13
|
|
|
* |
14
|
|
|
* @deprecated |
15
|
|
|
* @return WPInv_EUVat |
16
|
|
|
*/ |
17
|
|
|
public static function get_instance() { |
18
|
|
|
return new self(); |
19
|
|
|
} |
20
|
|
|
|
21
|
|
|
/** |
22
|
|
|
* Inits tax hooks. |
23
|
|
|
*/ |
24
|
|
|
public function init() { |
25
|
|
|
|
26
|
|
|
// If this is an admin page... |
27
|
|
|
if ( is_admin() ) { |
28
|
|
|
|
29
|
|
|
// Register our scripts. |
30
|
|
|
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) ); |
31
|
|
|
add_action( 'wpinv_settings_sections_taxes', array( $this, 'section_vat_settings' ) ); |
32
|
|
|
add_action( 'wpinv_settings_taxes', array( $this, 'vat_settings' ) ); |
33
|
|
|
add_filter( 'wpinv_settings_taxes-vat_sanitize', array( $this, 'sanitize_vat_settings' ) ); |
34
|
|
|
add_filter( 'wpinv_settings_taxes-vat_rates_sanitize', array( $this, 'sanitize_vat_rates' ) ); |
35
|
|
|
add_action( 'wp_ajax_wpinv_add_vat_class', array( $this, 'add_class' ) ); |
36
|
|
|
add_action( 'wp_ajax_nopriv_wpinv_add_vat_class', array( $this, 'add_class' ) ); |
37
|
|
|
add_action( 'wp_ajax_wpinv_delete_vat_class', array( $this, 'delete_class' ) ); |
38
|
|
|
add_action( 'wp_ajax_nopriv_wpinv_delete_vat_class', array( $this, 'delete_class' ) ); |
39
|
|
|
add_action( 'wp_ajax_wpinv_update_vat_rates', array( $this, 'update_eu_rates' ) ); |
40
|
|
|
add_action( 'wp_ajax_nopriv_wpinv_update_vat_rates', array( $this, 'update_eu_rates' ) ); |
41
|
|
|
} |
42
|
|
|
|
43
|
|
|
add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_vat_scripts' ) ); |
44
|
|
|
add_filter( 'wpinv_default_billing_country', array( $this, 'get_user_country' ), 10 ); |
45
|
|
|
add_filter( 'wpinv_get_user_country', array( $this, 'set_user_country' ), 10 ); |
46
|
|
|
add_action( 'wp_ajax_wpinv_vat_validate', array( $this, 'ajax_vat_validate' ) ); |
47
|
|
|
add_action( 'wp_ajax_nopriv_wpinv_vat_validate', array( $this, 'ajax_vat_validate' ) ); |
48
|
|
|
|
49
|
|
|
if ( wpinv_use_taxes() && self::allow_vat_rules() ) { |
50
|
|
|
add_filter( 'wpinv_tax_rate', array( $this, 'get_rate' ), 10, 4 ); |
51
|
|
|
} |
52
|
|
|
} |
53
|
|
|
|
54
|
|
|
public static function get_eu_states( $sort = true ) { |
55
|
|
|
$eu_states = array( 'AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE', 'GB', 'GR', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU', 'MT', 'NL', 'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'SE' ); |
56
|
|
|
if ( $sort ) { |
57
|
|
|
$sort = sort( $eu_states ); |
58
|
|
|
} |
59
|
|
|
|
60
|
|
|
return apply_filters( 'wpinv_get_eu_states', $eu_states, $sort ); |
61
|
|
|
} |
62
|
|
|
|
63
|
|
|
public static function get_gst_countries( $sort = true ) { |
64
|
|
|
$gst_countries = array( 'AU', 'NZ', 'CA', 'CN' ); |
65
|
|
|
|
66
|
|
|
if ( $sort ) { |
67
|
|
|
$sort = sort( $gst_countries ); |
68
|
|
|
} |
69
|
|
|
|
70
|
|
|
return apply_filters( 'wpinv_get_gst_countries', $gst_countries, $sort ); |
71
|
|
|
} |
72
|
|
|
|
73
|
|
|
public static function is_eu_state( $country_code ) { |
74
|
|
|
$return = !empty( $country_code ) && in_array( strtoupper( $country_code ), self::get_eu_states() ) ? true : false; |
75
|
|
|
|
76
|
|
|
return apply_filters( 'wpinv_is_eu_state', $return, $country_code ); |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
public static function is_gst_country( $country_code ) { |
80
|
|
|
$return = !empty( $country_code ) && in_array( strtoupper( $country_code ), self::get_gst_countries() ) ? true : false; |
81
|
|
|
|
82
|
|
|
return apply_filters( 'wpinv_is_gst_country', $return, $country_code ); |
83
|
|
|
} |
84
|
|
|
|
85
|
|
|
public function enqueue_vat_scripts() { |
86
|
|
|
if( wpinv_use_taxes() && wpinv_get_option( 'apply_vat_rules' ) ) { |
87
|
|
|
$this->load_vat_scripts(); |
88
|
|
|
} |
89
|
|
|
} |
90
|
|
|
|
91
|
|
|
public function load_vat_scripts(){ |
92
|
|
|
$suffix = '';//defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min'; |
93
|
|
|
|
94
|
|
|
wp_register_script( 'wpinv-vat-validation-script', WPINV_PLUGIN_URL . 'assets/js/jsvat' . $suffix . '.js', array( 'jquery' ), WPINV_VERSION ); |
95
|
|
|
wp_register_script( 'wpinv-vat-script', WPINV_PLUGIN_URL . 'assets/js/euvat' . $suffix . '.js', array( 'jquery' ), WPINV_VERSION ); |
96
|
|
|
|
97
|
|
|
$vat_name = $this->get_vat_name(); |
98
|
|
|
|
99
|
|
|
$vars = array(); |
100
|
|
|
$vars['UseTaxes'] = wpinv_use_taxes(); |
101
|
|
|
$vars['EUStates'] = self::get_eu_states(); |
102
|
|
|
$vars['NoRateSet'] = __( 'You have not set a rate. Do you want to continue?', 'invoicing' ); |
103
|
|
|
$vars['EmptyCompany'] = __( 'Please enter your registered company name!', 'invoicing' ); |
104
|
|
|
$vars['EmptyVAT'] = wp_sprintf( __( 'Please enter your %s number!', 'invoicing' ), $vat_name ); |
105
|
|
|
$vars['TotalsRefreshed'] = wp_sprintf( __( 'The invoice totals will be refreshed to update the %s.', 'invoicing' ), $vat_name ); |
106
|
|
|
$vars['ErrValidateVAT'] = wp_sprintf( __( 'Fail to validate the %s number!', 'invoicing' ), $vat_name ); |
107
|
|
|
$vars['ErrResetVAT'] = wp_sprintf( __( 'Fail to reset the %s number!', 'invoicing' ), $vat_name ); |
108
|
|
|
$vars['ErrInvalidVat'] = wp_sprintf( __( 'The %s number supplied does not have a valid format!', 'invoicing' ), $vat_name ); |
109
|
|
|
$vars['ErrInvalidResponse'] = __( 'An invalid response has been received from the server!', 'invoicing' ); |
110
|
|
|
$vars['ApplyVATRules'] = $vars['UseTaxes'] ? self::allow_vat_rules() : false; |
111
|
|
|
$vars['ErrResponse'] = __( 'The request response is invalid!', 'invoicing' ); |
112
|
|
|
$vars['ErrRateResponse'] = __( 'The get rate request response is invalid', 'invoicing' ); |
113
|
|
|
$vars['PageRefresh'] = __( 'The page will be refreshed in 10 seconds to show the new options.', 'invoicing' ); |
114
|
|
|
$vars['RequestResponseNotValidJSON'] = __( 'The get rate request response is not valid JSON', 'invoicing' ); |
115
|
|
|
$vars['GetRateRequestFailed'] = __( 'The get rate request failed: ', 'invoicing' ); |
116
|
|
|
$vars['NoRateInformationInResponse'] = __( 'The get rate request response does not contain any rate information', 'invoicing' ); |
117
|
|
|
$vars['RatesUpdated'] = __( 'The rates have been updated. Press the save button to record these new rates.', 'invoicing' ); |
118
|
|
|
$vars['IPAddressInformation'] = __( 'IP Address Information', 'invoicing' ); |
119
|
|
|
$vars['VatValidating'] = wp_sprintf( __( 'Validating %s number...', 'invoicing' ), $vat_name ); |
120
|
|
|
$vars['VatReseting'] = __( 'Reseting...', 'invoicing' ); |
121
|
|
|
$vars['VatValidated'] = wp_sprintf( __( '%s number validated', 'invoicing' ), $vat_name ); |
122
|
|
|
$vars['VatNotValidated'] = wp_sprintf( __( '%s number not validated', 'invoicing' ), $vat_name ); |
123
|
|
|
$vars['ConfirmDeleteClass'] = __( 'Are you sure you wish to delete this rates class?', 'invoicing' ); |
124
|
|
|
$vars['isFront'] = is_admin() ? false : true; |
125
|
|
|
$vars['baseCountry'] = wpinv_get_default_country(); |
126
|
|
|
$vars['disableVATSameCountry'] = ( self::same_country_rule() == 'no' ? true : false ); |
127
|
|
|
$vars['disableVATSimpleCheck'] = wpinv_get_option( 'vat_offline_check' ) ? true : false; |
128
|
|
|
|
129
|
|
|
wp_enqueue_script( 'wpinv-vat-validation-script' ); |
130
|
|
|
wp_enqueue_script( 'wpinv-vat-script' ); |
131
|
|
|
wp_localize_script( 'wpinv-vat-script', 'WPInv_VAT_Vars', $vars ); |
132
|
|
|
} |
133
|
|
|
|
134
|
|
|
public static function enqueue_admin_scripts() { |
135
|
|
|
if( isset( $_GET['page'] ) && 'wpinv-settings' == $_GET['page'] ) { |
136
|
|
|
self::load_vat_scripts(); |
|
|
|
|
137
|
|
|
} |
138
|
|
|
} |
139
|
|
|
|
140
|
|
|
public static function section_vat_settings( $sections ) { |
141
|
|
|
if ( !empty( $sections ) ) { |
142
|
|
|
$sections['vat'] = __( 'EU VAT Settings', 'invoicing' ); |
143
|
|
|
|
144
|
|
|
if ( self::allow_vat_classes() ) { |
145
|
|
|
$sections['vat_rates'] = __( 'EU VAT Rates', 'invoicing' ); |
146
|
|
|
} |
147
|
|
|
} |
148
|
|
|
return $sections; |
149
|
|
|
} |
150
|
|
|
|
151
|
|
|
public static function vat_rates_settings() { |
152
|
|
|
$vat_classes = self::get_rate_classes(); |
153
|
|
|
$vat_rates = array(); |
154
|
|
|
$vat_class = isset( $_REQUEST['wpi_sub'] ) && $_REQUEST['wpi_sub'] !== '' && isset( $vat_classes[$_REQUEST['wpi_sub']] )? sanitize_text_field( $_REQUEST['wpi_sub'] ) : '_new'; |
155
|
|
|
$current_url = remove_query_arg( 'wpi_sub' ); |
156
|
|
|
|
157
|
|
|
$vat_rates['vat_rates_header'] = array( |
158
|
|
|
'id' => 'vat_rates_header', |
159
|
|
|
'name' => '<h3>' . __( 'Manage VAT Rates', 'invoicing' ) . '</h3>', |
160
|
|
|
'desc' => '', |
161
|
|
|
'type' => 'header', |
162
|
|
|
'size' => 'regular' |
163
|
|
|
); |
164
|
|
|
$vat_rates['vat_rates_class'] = array( |
165
|
|
|
'id' => 'vat_rates_class', |
166
|
|
|
'name' => __( 'Edit VAT Rates', 'invoicing' ), |
167
|
|
|
'desc' => __( 'The standard rate will apply where no explicit rate is provided.', 'invoicing' ), |
168
|
|
|
'type' => 'select', |
169
|
|
|
'options' => array_merge( $vat_classes, array( '_new' => __( 'Add New Rate Class', 'invoicing' ) ) ), |
170
|
|
|
'placeholder' => __( 'Select a VAT Rate', 'invoicing' ), |
171
|
|
|
'selected' => $vat_class, |
172
|
|
|
'class' => 'wpi_select2', |
173
|
|
|
'onchange' => 'document.location.href="' . $current_url . '&wpi_sub=" + this.value;', |
174
|
|
|
); |
175
|
|
|
|
176
|
|
|
if ( $vat_class != '_standard' && $vat_class != '_new' ) { |
177
|
|
|
$vat_rates['vat_rate_delete'] = array( |
178
|
|
|
'id' => 'vat_rate_delete', |
179
|
|
|
'type' => 'vat_rate_delete', |
180
|
|
|
); |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
if ( $vat_class == '_new' ) { |
184
|
|
|
$vat_rates['vat_rates_settings'] = array( |
185
|
|
|
'id' => 'vat_rates_settings', |
186
|
|
|
'name' => '<h3>' . __( 'Add New Rate Class', 'invoicing' ) . '</h3>', |
187
|
|
|
'type' => 'header', |
188
|
|
|
); |
189
|
|
|
$vat_rates['vat_rate_name'] = array( |
190
|
|
|
'id' => 'vat_rate_name', |
191
|
|
|
'name' => __( 'Name', 'invoicing' ), |
192
|
|
|
'desc' => __( 'A short name for the new VAT Rate class', 'invoicing' ), |
193
|
|
|
'type' => 'text', |
194
|
|
|
'size' => 'regular', |
195
|
|
|
); |
196
|
|
|
$vat_rates['vat_rate_desc'] = array( |
197
|
|
|
'id' => 'vat_rate_desc', |
198
|
|
|
'name' => __( 'Description', 'invoicing' ), |
199
|
|
|
'desc' => __( 'Manage VAT Rate class', 'invoicing' ), |
200
|
|
|
'type' => 'text', |
201
|
|
|
'size' => 'regular', |
202
|
|
|
); |
203
|
|
|
$vat_rates['vat_rate_add'] = array( |
204
|
|
|
'id' => 'vat_rate_add', |
205
|
|
|
'type' => 'vat_rate_add', |
206
|
|
|
); |
207
|
|
|
} else { |
208
|
|
|
$vat_rates['vat_rates'] = array( |
209
|
|
|
'id' => 'vat_rates', |
210
|
|
|
'name' => '<h3>' . $vat_classes[$vat_class] . '</h3>', |
211
|
|
|
'desc' => self::get_class_desc( $vat_class ), |
212
|
|
|
'type' => 'vat_rates', |
213
|
|
|
); |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
return $vat_rates; |
217
|
|
|
} |
218
|
|
|
|
219
|
|
|
public static function vat_settings( $settings ) { |
220
|
|
|
if ( !empty( $settings ) ) { |
221
|
|
|
$vat_settings = array(); |
222
|
|
|
$vat_settings['vat_company_title'] = array( |
223
|
|
|
'id' => 'vat_company_title', |
224
|
|
|
'name' => '<h3>' . __( 'Your Company Details', 'invoicing' ) . '</h3>', |
225
|
|
|
'desc' => '', |
226
|
|
|
'type' => 'header', |
227
|
|
|
'size' => 'regular' |
228
|
|
|
); |
229
|
|
|
|
230
|
|
|
$vat_settings['vat_company_name'] = array( |
231
|
|
|
'id' => 'vat_company_name', |
232
|
|
|
'name' => __( 'Your Company Name', 'invoicing' ), |
233
|
|
|
'desc' => wp_sprintf(__( 'Your company name as it appears on your VAT return, you can verify it via your VAT ID on the %sEU VIES System.%s', 'invoicing' ), '<a href="http://ec.europa.eu/taxation_customs/vies/" target="_blank">', '</a>' ), |
234
|
|
|
'type' => 'text', |
235
|
|
|
'size' => 'regular', |
236
|
|
|
); |
237
|
|
|
|
238
|
|
|
$vat_settings['vat_number'] = array( |
239
|
|
|
'id' => 'vat_number', |
240
|
|
|
'name' => __( 'Your VAT Number', 'invoicing' ), |
241
|
|
|
'type' => 'vat_number', |
242
|
|
|
'size' => 'regular', |
243
|
|
|
); |
244
|
|
|
|
245
|
|
|
$vat_settings['vat_settings_title'] = array( |
246
|
|
|
'id' => 'vat_settings_title', |
247
|
|
|
'name' => '<h3>' . __( 'Apply VAT Settings', 'invoicing' ) . '</h3>', |
248
|
|
|
'desc' => '', |
249
|
|
|
'type' => 'header', |
250
|
|
|
'size' => 'regular' |
251
|
|
|
); |
252
|
|
|
|
253
|
|
|
$vat_settings['apply_vat_rules'] = array( |
254
|
|
|
'id' => 'apply_vat_rules', |
255
|
|
|
'name' => __( 'Enable VAT Rules', 'invoicing' ), |
256
|
|
|
'desc' => __( 'Apply VAT to consumer sales from IP addresses within the EU, even if the billing address is outside the EU.', 'invoicing' ) . '<br><font style="color:red">' . __( 'Do not disable unless you know what you are doing.', 'invoicing' ) . '</font>', |
257
|
|
|
'type' => 'checkbox', |
258
|
|
|
'std' => '1' |
259
|
|
|
); |
260
|
|
|
|
261
|
|
|
/* |
262
|
|
|
$vat_settings['vat_allow_classes'] = array( |
263
|
|
|
'id' => 'vat_allow_classes', |
264
|
|
|
'name' => __( 'Allow the use of VAT rate classes', 'invoicing' ), |
265
|
|
|
'desc' => __( 'When enabled this option makes it possible to define alternative rate classes so rates for items that do not use the standard VAT rate in all member states can be defined.<br>A menu option will appear under the "Invoicing -> Settings -> Taxes -> EU VAT Rates" menu heading that will take you to a page on which new classes can be defined and rates entered. A meta-box will appear in the invoice page in which you are able to select one of the alternative classes you create so the rates associated with the class will be applied to invoice.<br>By default the standard rates class will be used just as they are when this option is not enabled.', 'invoicing' ), |
266
|
|
|
'type' => 'checkbox' |
267
|
|
|
); |
268
|
|
|
*/ |
269
|
|
|
|
270
|
|
|
$vat_settings['vat_prevent_b2c_purchase'] = array( |
271
|
|
|
'id' => 'vat_prevent_b2c_purchase', |
272
|
|
|
'name' => __( 'Prevent EU B2C Sales', 'invoicing' ), |
273
|
|
|
'desc' => __( 'Enable this option if you are not registered for VAT in the EU.', 'invoicing' ), |
274
|
|
|
'type' => 'checkbox' |
275
|
|
|
); |
276
|
|
|
|
277
|
|
|
|
278
|
|
|
|
279
|
|
|
$vat_settings['vat_same_country_rule'] = array( |
280
|
|
|
'id' => 'vat_same_country_rule', |
281
|
|
|
'name' => __( 'Same Country Rule', 'invoicing' ), |
282
|
|
|
'desc' => __( 'Select how you want to handle VAT charge if sales are in the same country as the base country.', 'invoicing' ), |
283
|
|
|
'type' => 'select', |
284
|
|
|
'options' => array( |
285
|
|
|
'' => __( 'Normal', 'invoicing' ), |
286
|
|
|
'no' => __( 'No VAT', 'invoicing' ), |
287
|
|
|
'always' => __( 'Always apply VAT', 'invoicing' ), |
288
|
|
|
), |
289
|
|
|
'placeholder' => __( 'Select an option', 'invoicing' ), |
290
|
|
|
'std' => '', |
291
|
|
|
'class' => 'wpi_select2', |
292
|
|
|
); |
293
|
|
|
|
294
|
|
|
$vat_settings['vat_checkout_title'] = array( |
295
|
|
|
'id' => 'vat_checkout_title', |
296
|
|
|
'name' => '<h3>' . __( 'Checkout Fields', 'invoicing' ) . '</h3>', |
297
|
|
|
'desc' => '', |
298
|
|
|
'type' => 'header', |
299
|
|
|
'size' => 'regular' |
300
|
|
|
); |
301
|
|
|
|
302
|
|
|
$vat_settings['vies_validation_title'] = array( |
303
|
|
|
'id' => 'vies_validation_title', |
304
|
|
|
'name' => '<h3>' . __( 'VIES Validation', 'invoicing' ) . '</h3>', |
305
|
|
|
'desc' => '', |
306
|
|
|
'type' => 'header', |
307
|
|
|
'size' => 'regular' |
308
|
|
|
); |
309
|
|
|
|
310
|
|
|
$vat_settings['vat_vies_check'] = array( |
311
|
|
|
'id' => 'vat_vies_check', |
312
|
|
|
'name' => __( 'Disable VIES VAT ID Check', 'invoicing' ), |
313
|
|
|
'desc' => wp_sprintf( __( 'Prevent VAT numbers from being validated by the %sEU VIES System.%s', 'invoicing' ), '<a href="http://ec.europa.eu/taxation_customs/vies/" target="_blank">', '</a>' ), |
314
|
|
|
'type' => 'checkbox' |
315
|
|
|
); |
316
|
|
|
|
317
|
|
|
$vat_settings['vat_disable_company_name_check'] = array( |
318
|
|
|
'id' => 'vat_disable_company_name_check', |
319
|
|
|
'name' => __( 'Disable VIES Name Check', 'invoicing' ), |
320
|
|
|
'desc' => wp_sprintf( __( 'Prevent company name from being validated by the %sEU VIES System.%s', 'invoicing' ), '<a href="http://ec.europa.eu/taxation_customs/vies/" target="_blank">', '</a>' ), |
321
|
|
|
'type' => 'checkbox' |
322
|
|
|
); |
323
|
|
|
|
324
|
|
|
$vat_settings['vat_offline_check'] = array( |
325
|
|
|
'id' => 'vat_offline_check', |
326
|
|
|
'name' => __( 'Disable Basic Checks', 'invoicing' ), |
327
|
|
|
'desc' => __( 'Disable basic JS checks for correct format of VAT number. (Not Recommended)', 'invoicing' ), |
328
|
|
|
'type' => 'checkbox' |
329
|
|
|
); |
330
|
|
|
|
331
|
|
|
|
332
|
|
|
$settings['vat'] = $vat_settings; |
333
|
|
|
|
334
|
|
|
if ( self::allow_vat_classes() ) { |
335
|
|
|
$settings['vat_rates'] = self::vat_rates_settings(); |
336
|
|
|
} |
337
|
|
|
|
338
|
|
|
$eu_fallback_rate = array( |
339
|
|
|
'id' => 'eu_fallback_rate', |
340
|
|
|
'name' => '<h3>' . __( 'VAT rate for EU member states', 'invoicing' ) . '</h3>', |
341
|
|
|
'type' => 'eu_fallback_rate', |
342
|
|
|
'desc' => __( 'Enter the VAT rate to be charged for EU member states. You can edit the rates for each member state when a country rate has been set up by pressing this button.', 'invoicing' ), |
343
|
|
|
'std' => '20', |
344
|
|
|
'size' => 'small' |
345
|
|
|
); |
346
|
|
|
$settings['rates']['eu_fallback_rate'] = $eu_fallback_rate; |
347
|
|
|
} |
348
|
|
|
|
349
|
|
|
return $settings; |
350
|
|
|
} |
351
|
|
|
|
352
|
|
|
/** |
353
|
|
|
* |
354
|
|
|
* @deprecated |
355
|
|
|
*/ |
356
|
|
|
public static function maxmind_folder() { |
357
|
|
|
return false; |
358
|
|
|
} |
359
|
|
|
|
360
|
|
|
/** |
361
|
|
|
* |
362
|
|
|
* @deprecated |
363
|
|
|
*/ |
364
|
|
|
public static function geoip2_download_database() {} |
365
|
|
|
|
366
|
|
|
/** |
367
|
|
|
* |
368
|
|
|
* @deprecated |
369
|
|
|
*/ |
370
|
|
|
public static function geoip2_download_file() {} |
371
|
|
|
|
372
|
|
|
/** |
373
|
|
|
* @deprecated |
374
|
|
|
*/ |
375
|
|
|
public static function load_geoip2() {} |
376
|
|
|
|
377
|
|
|
/** |
378
|
|
|
* @deprecated |
379
|
|
|
*/ |
380
|
|
|
public static function geoip2_country_dbfile() { |
381
|
|
|
return false; |
382
|
|
|
} |
383
|
|
|
|
384
|
|
|
/** |
385
|
|
|
* @deprecated |
386
|
|
|
*/ |
387
|
|
|
public static function geoip2_city_dbfile() { |
388
|
|
|
return false; |
389
|
|
|
} |
390
|
|
|
|
391
|
|
|
/** |
392
|
|
|
* @deprecated |
393
|
|
|
*/ |
394
|
|
|
public static function geoip2_country_reader() { |
395
|
|
|
return false; |
396
|
|
|
} |
397
|
|
|
|
398
|
|
|
/** |
399
|
|
|
* @deprecated |
400
|
|
|
*/ |
401
|
|
|
public static function geoip2_city_reader() { |
402
|
|
|
return false; |
403
|
|
|
} |
404
|
|
|
|
405
|
|
|
/** |
406
|
|
|
* @deprecated |
407
|
|
|
*/ |
408
|
|
|
public static function geoip2_country_record() { |
409
|
|
|
return false; |
410
|
|
|
} |
411
|
|
|
|
412
|
|
|
/** |
413
|
|
|
* @deprecated |
414
|
|
|
*/ |
415
|
|
|
public static function geoip2_city_record() { |
416
|
|
|
return false; |
417
|
|
|
} |
418
|
|
|
|
419
|
|
|
/** |
420
|
|
|
* @deprecated |
421
|
|
|
*/ |
422
|
|
|
public static function geoip2_country_code() { |
423
|
|
|
wpinv_get_default_country(); |
424
|
|
|
} |
425
|
|
|
|
426
|
|
|
/** |
427
|
|
|
* @deprecated |
428
|
|
|
*/ |
429
|
|
|
public static function get_country_by_ip() { |
430
|
|
|
return getpaid_get_ip_country(); |
431
|
|
|
} |
432
|
|
|
|
433
|
|
|
public static function sanitize_vat_settings( $input ) { |
434
|
|
|
global $wpinv_options; |
435
|
|
|
|
436
|
|
|
$valid = false; |
437
|
|
|
$message = ''; |
438
|
|
|
|
439
|
|
|
if ( !empty( $wpinv_options['vat_vies_check'] ) ) { |
440
|
|
|
if ( empty( $wpinv_options['vat_offline_check'] ) ) { |
441
|
|
|
$valid = self::offline_check( $input['vat_number'] ); |
442
|
|
|
} else { |
443
|
|
|
$valid = true; |
444
|
|
|
} |
445
|
|
|
|
446
|
|
|
$message = $valid ? '' : __( 'VAT number not validated', 'invoicing' ); |
447
|
|
|
} else { |
448
|
|
|
$result = self::check_vat( $input['vat_number'] ); |
449
|
|
|
|
450
|
|
|
if ( empty( $result['valid'] ) ) { |
451
|
|
|
$valid = false; |
452
|
|
|
$message = $result['message']; |
453
|
|
|
} else { |
454
|
|
|
$valid = ( isset( $result['company'] ) && ( $result['company'] == '---' || ( strcasecmp( trim( $result['company'] ), trim( $input['vat_company_name'] ) ) == 0 ) ) ) || !empty( $wpinv_options['vat_disable_company_name_check'] ); |
|
|
|
|
455
|
|
|
$message = $valid ? '' : __( 'The company name associated with the VAT number provided is not the same as the company name provided.', 'invoicing' ); |
456
|
|
|
} |
457
|
|
|
} |
458
|
|
|
|
459
|
|
|
if ( $message && self::is_vat_validated() != $valid ) { |
460
|
|
|
add_settings_error( 'wpinv-notices', '', $message, ( $valid ? 'updated' : 'error' ) ); |
461
|
|
|
} |
462
|
|
|
|
463
|
|
|
$input['vat_valid'] = $valid; |
464
|
|
|
return $input; |
465
|
|
|
} |
466
|
|
|
|
467
|
|
|
public static function sanitize_vat_rates( $input ) { |
468
|
|
|
if( !wpinv_current_user_can_manage_invoicing() ) { |
469
|
|
|
add_settings_error( 'wpinv-notices', '', __( 'Your account does not have permission to add rate classes.', 'invoicing' ), 'error' ); |
470
|
|
|
return $input; |
471
|
|
|
} |
472
|
|
|
|
473
|
|
|
$vat_classes = self::get_rate_classes(); |
474
|
|
|
$vat_class = !empty( $_REQUEST['wpi_vat_class'] ) && isset( $vat_classes[$_REQUEST['wpi_vat_class']] )? sanitize_text_field( $_REQUEST['wpi_vat_class'] ) : ''; |
475
|
|
|
|
476
|
|
|
if ( empty( $vat_class ) ) { |
477
|
|
|
add_settings_error( 'wpinv-notices', '', __( 'No valid VAT rates class contained in the request to save rates.', 'invoicing' ), 'error' ); |
478
|
|
|
|
479
|
|
|
return $input; |
480
|
|
|
} |
481
|
|
|
|
482
|
|
|
$new_rates = ! empty( $_POST['vat_rates'] ) ? array_values( $_POST['vat_rates'] ) : array(); |
483
|
|
|
|
484
|
|
|
if ( $vat_class === '_standard' ) { |
485
|
|
|
// Save the active rates in the invoice settings |
486
|
|
|
update_option( 'wpinv_tax_rates', $new_rates ); |
487
|
|
|
} else { |
488
|
|
|
// Get the existing set of rates |
489
|
|
|
$rates = self::get_non_standard_rates(); |
490
|
|
|
$rates[$vat_class] = $new_rates; |
491
|
|
|
|
492
|
|
|
update_option( 'wpinv_vat_rates', $rates ); |
493
|
|
|
} |
494
|
|
|
|
495
|
|
|
return $input; |
496
|
|
|
} |
497
|
|
|
|
498
|
|
|
public static function add_class() { |
499
|
|
|
$response = array(); |
500
|
|
|
$response['success'] = false; |
501
|
|
|
|
502
|
|
|
if ( !wpinv_current_user_can_manage_invoicing() ) { |
503
|
|
|
$response['error'] = __( 'Invalid access!', 'invoicing' ); |
504
|
|
|
wp_send_json( $response ); |
505
|
|
|
} |
506
|
|
|
|
507
|
|
|
$vat_class_name = !empty( $_POST['name'] ) ? sanitize_text_field( $_POST['name'] ) : false; |
508
|
|
|
$vat_class_desc = !empty( $_POST['desc'] ) ? sanitize_text_field( $_POST['desc'] ) : false; |
509
|
|
|
|
510
|
|
|
if ( empty( $vat_class_name ) ) { |
511
|
|
|
$response['error'] = __( 'Select the VAT rate name', 'invoicing' ); |
512
|
|
|
wp_send_json( $response ); |
513
|
|
|
} |
514
|
|
|
|
515
|
|
|
$vat_classes = (array)self::get_rate_classes(); |
516
|
|
|
|
517
|
|
|
if ( !empty( $vat_classes ) && in_array( strtolower( $vat_class_name ), array_map( 'strtolower', array_values( $vat_classes ) ) ) ) { |
518
|
|
|
$response['error'] = wp_sprintf( __( 'A VAT Rate name "%s" already exists', 'invoicing' ), $vat_class_name ); |
519
|
|
|
wp_send_json( $response ); |
520
|
|
|
} |
521
|
|
|
|
522
|
|
|
$rate_class_key = normalize_whitespace( 'wpi-' . $vat_class_name ); |
523
|
|
|
$rate_class_key = sanitize_key( str_replace( " ", "-", $rate_class_key ) ); |
524
|
|
|
|
525
|
|
|
$vat_classes = (array)self::get_rate_classes( true ); |
526
|
|
|
$vat_classes[$rate_class_key] = array( 'name' => $vat_class_name, 'desc' => $vat_class_desc ); |
527
|
|
|
|
528
|
|
|
update_option( '_wpinv_vat_rate_classes', $vat_classes ); |
529
|
|
|
|
530
|
|
|
$response['success'] = true; |
531
|
|
|
$response['redirect'] = admin_url( 'admin.php?page=wpinv-settings&tab=taxes§ion=vat_rates&wpi_sub=' . $rate_class_key ); |
532
|
|
|
|
533
|
|
|
wp_send_json( $response ); |
534
|
|
|
} |
535
|
|
|
|
536
|
|
|
public static function delete_class() { |
537
|
|
|
$response = array(); |
538
|
|
|
$response['success'] = false; |
539
|
|
|
|
540
|
|
|
if ( !wpinv_current_user_can_manage_invoicing() || !isset( $_POST['class'] ) ) { |
541
|
|
|
$response['error'] = __( 'Invalid access!', 'invoicing' ); |
542
|
|
|
wp_send_json( $response ); |
543
|
|
|
} |
544
|
|
|
|
545
|
|
|
$vat_class = isset( $_POST['class'] ) && $_POST['class'] !== '' ? sanitize_text_field( $_POST['class'] ) : false; |
546
|
|
|
$vat_classes = (array)self::get_rate_classes(); |
547
|
|
|
|
548
|
|
|
if ( !isset( $vat_classes[$vat_class] ) ) { |
549
|
|
|
$response['error'] = __( 'Requested class does not exists', 'invoicing' ); |
550
|
|
|
wp_send_json( $response ); |
551
|
|
|
} |
552
|
|
|
|
553
|
|
|
if ( $vat_class == '_new' || $vat_class == '_standard' ) { |
554
|
|
|
$response['error'] = __( 'You can not delete standard rates class', 'invoicing' ); |
555
|
|
|
wp_send_json( $response ); |
556
|
|
|
} |
557
|
|
|
|
558
|
|
|
$vat_classes = (array)self::get_rate_classes( true ); |
559
|
|
|
unset( $vat_classes[$vat_class] ); |
560
|
|
|
|
561
|
|
|
update_option( '_wpinv_vat_rate_classes', $vat_classes ); |
562
|
|
|
|
563
|
|
|
$response['success'] = true; |
564
|
|
|
$response['redirect'] = admin_url( 'admin.php?page=wpinv-settings&tab=taxes§ion=vat_rates&wpi_sub=_new' ); |
565
|
|
|
|
566
|
|
|
wp_send_json( $response ); |
567
|
|
|
} |
568
|
|
|
|
569
|
|
|
public static function update_eu_rates() { |
570
|
|
|
$response = array(); |
571
|
|
|
$response['success'] = false; |
572
|
|
|
$response['error'] = null; |
573
|
|
|
$response['data'] = null; |
574
|
|
|
|
575
|
|
|
if ( !wpinv_current_user_can_manage_invoicing() ) { |
576
|
|
|
$response['error'] = __( 'Invalid access!', 'invoicing' ); |
577
|
|
|
wp_send_json( $response ); |
578
|
|
|
} |
579
|
|
|
|
580
|
|
|
$group = !empty( $_POST['group'] ) ? sanitize_text_field( $_POST['group'] ) : ''; |
581
|
|
|
$euvatrates = self::request_euvatrates( $group ); |
582
|
|
|
|
583
|
|
|
if ( !empty( $euvatrates ) ) { |
584
|
|
|
if ( !empty( $euvatrates['success'] ) && !empty( $euvatrates['rates'] ) ) { |
585
|
|
|
$response['success'] = true; |
586
|
|
|
$response['data']['rates'] = $euvatrates['rates']; |
587
|
|
|
} else if ( !empty( $euvatrates['error'] ) ) { |
588
|
|
|
$response['error'] = $euvatrates['error']; |
589
|
|
|
} |
590
|
|
|
} |
591
|
|
|
|
592
|
|
|
wp_send_json( $response ); |
593
|
|
|
} |
594
|
|
|
|
595
|
|
|
/** |
596
|
|
|
* @deprecated |
597
|
|
|
*/ |
598
|
|
|
public static function hide_vat_fields() {} |
599
|
|
|
|
600
|
|
|
public static function same_country_rule() { |
601
|
|
|
$same_country_rule = wpinv_get_option( 'vat_same_country_rule' ); |
602
|
|
|
|
603
|
|
|
return apply_filters( 'wpinv_vat_same_country_rule', $same_country_rule ); |
604
|
|
|
} |
605
|
|
|
|
606
|
|
|
/** |
607
|
|
|
* Retrieves the vat name. |
608
|
|
|
*/ |
609
|
|
|
public function get_vat_name() { |
610
|
|
|
$vat_name = wpinv_get_option( 'vat_name' ); |
611
|
|
|
return empty( $vat_name ) ? __( 'VAT', 'invoicing' ) : sanitize_text_field( $vat_name ); |
612
|
|
|
} |
613
|
|
|
|
614
|
|
|
public static function get_company_name() { |
615
|
|
|
$company_name = wpinv_get_option( 'vat_company_name' ); |
616
|
|
|
|
617
|
|
|
return apply_filters( 'wpinv_get_owner_company_name', $company_name ); |
618
|
|
|
} |
619
|
|
|
|
620
|
|
|
public static function get_vat_number() { |
621
|
|
|
$vat_number = wpinv_get_option( 'vat_number' ); |
622
|
|
|
|
623
|
|
|
return apply_filters( 'wpinv_get_owner_vat_number', $vat_number ); |
624
|
|
|
} |
625
|
|
|
|
626
|
|
|
public static function is_vat_validated() { |
627
|
|
|
$validated = self::get_vat_number() && wpinv_get_option( 'vat_valid' ); |
628
|
|
|
|
629
|
|
|
return apply_filters( 'wpinv_is_owner_vat_validated', $validated ); |
630
|
|
|
} |
631
|
|
|
|
632
|
|
|
public static function sanitize_vat( $vat_number, $country_code = '' ) { |
633
|
|
|
$vat_number = str_replace( array(' ', '.', '-', '_', ',' ), '', strtoupper( trim( $vat_number ) ) ); |
634
|
|
|
|
635
|
|
|
if ( empty( $country_code ) ) { |
636
|
|
|
$country_code = substr( $vat_number, 0, 2 ); |
637
|
|
|
} |
638
|
|
|
|
639
|
|
|
if ( strpos( $vat_number , $country_code ) === 0 ) { |
640
|
|
|
$vat = str_replace( $country_code, '', $vat_number ); |
641
|
|
|
} else { |
642
|
|
|
$vat = $country_code . $vat_number; |
643
|
|
|
} |
644
|
|
|
|
645
|
|
|
$return = array(); |
646
|
|
|
$return['vat'] = $vat; |
647
|
|
|
$return['iso'] = $country_code; |
648
|
|
|
$return['vat_number'] = $country_code . $vat; |
649
|
|
|
|
650
|
|
|
return $return; |
651
|
|
|
} |
652
|
|
|
|
653
|
|
|
public static function offline_check( $vat_number, $country_code = '', $formatted = false ) { |
654
|
|
|
$vat = self::sanitize_vat( $vat_number, $country_code ); |
655
|
|
|
$vat_number = $vat['vat_number']; |
656
|
|
|
$country_code = $vat['iso']; |
657
|
|
|
$regex = array(); |
658
|
|
|
|
659
|
|
|
switch ( $country_code ) { |
660
|
|
|
case 'AT': |
661
|
|
|
$regex[] = '/^(AT)U(\d{8})$/'; // Austria |
662
|
|
|
break; |
663
|
|
|
case 'BE': |
664
|
|
|
$regex[] = '/^(BE)(0?\d{9})$/'; // Belgium |
665
|
|
|
break; |
666
|
|
|
case 'BG': |
667
|
|
|
$regex[] = '/^(BG)(\d{9,10})$/'; // Bulgaria |
668
|
|
|
break; |
669
|
|
|
case 'CH': |
670
|
|
|
case 'CHE': |
671
|
|
|
$regex[] = '/^(CHE)(\d{9})MWST$/'; // Switzerland (Not EU) |
672
|
|
|
break; |
673
|
|
|
case 'CY': |
674
|
|
|
$regex[] = '/^(CY)([0-5|9]\d{7}[A-Z])$/'; // Cyprus |
675
|
|
|
break; |
676
|
|
|
case 'CZ': |
677
|
|
|
$regex[] = '/^(CZ)(\d{8,13})$/'; // Czech Republic |
678
|
|
|
break; |
679
|
|
|
case 'DE': |
680
|
|
|
$regex[] = '/^(DE)([1-9]\d{8})$/'; // Germany |
681
|
|
|
break; |
682
|
|
|
case 'DK': |
683
|
|
|
$regex[] = '/^(DK)(\d{8})$/'; // Denmark |
684
|
|
|
break; |
685
|
|
|
case 'EE': |
686
|
|
|
$regex[] = '/^(EE)(10\d{7})$/'; // Estonia |
687
|
|
|
break; |
688
|
|
|
case 'EL': |
689
|
|
|
$regex[] = '/^(EL)(\d{9})$/'; // Greece |
690
|
|
|
break; |
691
|
|
|
case 'ES': |
692
|
|
|
$regex[] = '/^(ES)([A-Z]\d{8})$/'; // Spain (National juridical entities) |
693
|
|
|
$regex[] = '/^(ES)([A-H|N-S|W]\d{7}[A-J])$/'; // Spain (Other juridical entities) |
694
|
|
|
$regex[] = '/^(ES)([0-9|Y|Z]\d{7}[A-Z])$/'; // Spain (Personal entities type 1) |
695
|
|
|
$regex[] = '/^(ES)([K|L|M|X]\d{7}[A-Z])$/'; // Spain (Personal entities type 2) |
696
|
|
|
break; |
697
|
|
|
case 'EU': |
698
|
|
|
$regex[] = '/^(EU)(\d{9})$/'; // EU-type |
699
|
|
|
break; |
700
|
|
|
case 'FI': |
701
|
|
|
$regex[] = '/^(FI)(\d{8})$/'; // Finland |
702
|
|
|
break; |
703
|
|
|
case 'FR': |
704
|
|
|
$regex[] = '/^(FR)(\d{11})$/'; // France (1) |
705
|
|
|
$regex[] = '/^(FR)[(A-H)|(J-N)|(P-Z)](\d{10})$/'; // France (2) |
706
|
|
|
$regex[] = '/^(FR)\d[(A-H)|(J-N)|(P-Z)](\d{9})$/'; // France (3) |
707
|
|
|
$regex[] = '/^(FR)[(A-H)|(J-N)|(P-Z)]{2}(\d{9})$/'; // France (4) |
708
|
|
|
break; |
709
|
|
|
case 'GB': |
710
|
|
|
$regex[] = '/^(GB)?(\d{9})$/'; // UK (Standard) |
711
|
|
|
$regex[] = '/^(GB)?(\d{12})$/'; // UK (Branches) |
712
|
|
|
$regex[] = '/^(GB)?(GD\d{3})$/'; // UK (Government) |
713
|
|
|
$regex[] = '/^(GB)?(HA\d{3})$/'; // UK (Health authority) |
714
|
|
|
break; |
715
|
|
|
case 'GR': |
716
|
|
|
$regex[] = '/^(GR)(\d{8,9})$/'; // Greece |
717
|
|
|
break; |
718
|
|
|
case 'HR': |
719
|
|
|
$regex[] = '/^(HR)(\d{11})$/'; // Croatia |
720
|
|
|
break; |
721
|
|
|
case 'HU': |
722
|
|
|
$regex[] = '/^(HU)(\d{8})$/'; // Hungary |
723
|
|
|
break; |
724
|
|
|
case 'IE': |
725
|
|
|
$regex[] = '/^(IE)(\d{7}[A-W])$/'; // Ireland (1) |
726
|
|
|
$regex[] = '/^(IE)([7-9][A-Z\*\+)]\d{5}[A-W])$/'; // Ireland (2) |
727
|
|
|
$regex[] = '/^(IE)(\d{7}[A-Z][AH])$/'; // Ireland (3) (new format from 1 Jan 2013) |
728
|
|
|
break; |
729
|
|
|
case 'IT': |
730
|
|
|
$regex[] = '/^(IT)(\d{11})$/'; // Italy |
731
|
|
|
break; |
732
|
|
|
case 'LV': |
733
|
|
|
$regex[] = '/^(LV)(\d{11})$/'; // Latvia |
734
|
|
|
break; |
735
|
|
|
case 'LT': |
736
|
|
|
$regex[] = '/^(LT)(\d{9}|\d{12})$/'; // Lithuania |
737
|
|
|
break; |
738
|
|
|
case 'LU': |
739
|
|
|
$regex[] = '/^(LU)(\d{8})$/'; // Luxembourg |
740
|
|
|
break; |
741
|
|
|
case 'MT': |
742
|
|
|
$regex[] = '/^(MT)([1-9]\d{7})$/'; // Malta |
743
|
|
|
break; |
744
|
|
|
case 'NL': |
745
|
|
|
$regex[] = '/^(NL)(\d{9})B\d{2}$/'; // Netherlands |
746
|
|
|
break; |
747
|
|
|
case 'NO': |
748
|
|
|
$regex[] = '/^(NO)(\d{9})$/'; // Norway (Not EU) |
749
|
|
|
break; |
750
|
|
|
case 'PL': |
751
|
|
|
$regex[] = '/^(PL)(\d{10})$/'; // Poland |
752
|
|
|
break; |
753
|
|
|
case 'PT': |
754
|
|
|
$regex[] = '/^(PT)(\d{9})$/'; // Portugal |
755
|
|
|
break; |
756
|
|
|
case 'RO': |
757
|
|
|
$regex[] = '/^(RO)([1-9]\d{1,9})$/'; // Romania |
758
|
|
|
break; |
759
|
|
|
case 'RS': |
760
|
|
|
$regex[] = '/^(RS)(\d{9})$/'; // Serbia (Not EU) |
761
|
|
|
break; |
762
|
|
|
case 'SI': |
763
|
|
|
$regex[] = '/^(SI)([1-9]\d{7})$/'; // Slovenia |
764
|
|
|
break; |
765
|
|
|
case 'SK': |
766
|
|
|
$regex[] = '/^(SK)([1-9]\d[(2-4)|(6-9)]\d{7})$/'; // Slovakia Republic |
767
|
|
|
break; |
768
|
|
|
case 'SE': |
769
|
|
|
$regex[] = '/^(SE)(\d{10}01)$/'; // Sweden |
770
|
|
|
break; |
771
|
|
|
default: |
772
|
|
|
$regex = array(); |
773
|
|
|
break; |
774
|
|
|
} |
775
|
|
|
|
776
|
|
|
if ( empty( $regex ) ) { |
777
|
|
|
return false; |
778
|
|
|
} |
779
|
|
|
|
780
|
|
|
foreach ( $regex as $pattern ) { |
781
|
|
|
$matches = null; |
782
|
|
|
preg_match_all( $pattern, $vat_number, $matches ); |
783
|
|
|
|
784
|
|
|
if ( !empty( $matches[1][0] ) && !empty( $matches[2][0] ) ) { |
785
|
|
|
if ( $formatted ) { |
786
|
|
|
return array( 'code' => $matches[1][0], 'number' => $matches[2][0] ); |
787
|
|
|
} else { |
788
|
|
|
return true; |
789
|
|
|
} |
790
|
|
|
} |
791
|
|
|
} |
792
|
|
|
|
793
|
|
|
return false; |
794
|
|
|
} |
795
|
|
|
|
796
|
|
|
public static function vies_check( $vat_number, $country_code = '', $result = false ) { |
797
|
|
|
$vat = self::sanitize_vat( $vat_number, $country_code ); |
798
|
|
|
$vat_number = $vat['vat']; |
799
|
|
|
$iso = $vat['iso']; |
800
|
|
|
|
801
|
|
|
$url = 'http://ec.europa.eu/taxation_customs/vies/viesquer.do?ms=' . urlencode( $iso ) . '&iso=' . urlencode( $iso ) . '&vat=' . urlencode( $vat_number ); |
802
|
|
|
|
803
|
|
|
if ( ini_get( 'allow_url_fopen' ) ) { |
804
|
|
|
$response = file_get_contents( $url ); |
805
|
|
|
} else if ( function_exists( 'curl_init' ) ) { |
806
|
|
|
$ch = curl_init(); |
807
|
|
|
|
808
|
|
|
curl_setopt( $ch, CURLOPT_URL, $url ); |
|
|
|
|
809
|
|
|
curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 30 ); |
810
|
|
|
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true ); |
811
|
|
|
curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, 0 ); |
812
|
|
|
curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, 0 ); |
813
|
|
|
|
814
|
|
|
$response = curl_exec( $ch ); |
|
|
|
|
815
|
|
|
|
816
|
|
|
if ( curl_errno( $ch ) ) { |
|
|
|
|
817
|
|
|
wpinv_error_log( curl_error( $ch ), 'VIES CHECK ERROR' ); |
|
|
|
|
818
|
|
|
$response = ''; |
819
|
|
|
} |
820
|
|
|
|
821
|
|
|
curl_close( $ch ); |
|
|
|
|
822
|
|
|
} else { |
823
|
|
|
wpinv_error_log( 'To use VIES CHECK you must have allow_url_fopen is ON or cURL installed & active on your server.', 'VIES CHECK ERROR' ); |
824
|
|
|
} |
825
|
|
|
|
826
|
|
|
if ( empty( $response ) ) { |
827
|
|
|
return $result; |
828
|
|
|
} |
829
|
|
|
|
830
|
|
|
if ( preg_match( '/invalid VAT number/i', $response ) ) { |
|
|
|
|
831
|
|
|
return false; |
832
|
|
|
} else if ( preg_match( '/valid VAT number/i', $response, $matches ) ) { |
833
|
|
|
$content = explode( "valid VAT number", htmlentities( $response ) ); |
834
|
|
|
|
835
|
|
|
if ( !empty( $content[1] ) ) { |
836
|
|
|
preg_match_all( '/<tr>(.*?)<td.*?>(.*?)<\/td>(.*?)<\/tr>/si', html_entity_decode( $content[1] ), $matches ); |
837
|
|
|
|
838
|
|
|
if ( !empty( $matches[2] ) && $matches[3] ) { |
839
|
|
|
$return = array(); |
840
|
|
|
|
841
|
|
|
foreach ( $matches[2] as $key => $label ) { |
842
|
|
|
$label = trim( $label ); |
843
|
|
|
|
844
|
|
|
switch ( strtolower( $label ) ) { |
845
|
|
|
case 'member state': |
846
|
|
|
$return['state'] = trim( strip_tags( $matches[3][$key] ) ); |
847
|
|
|
break; |
848
|
|
|
case 'vat number': |
849
|
|
|
$return['number'] = trim( strip_tags( $matches[3][$key] ) ); |
850
|
|
|
break; |
851
|
|
|
case 'name': |
852
|
|
|
$return['company'] = trim( strip_tags( $matches[3][$key] ) ); |
853
|
|
|
break; |
854
|
|
|
case 'address': |
855
|
|
|
$address = str_replace( array( "<br><br>", "<br /><br />", "<br/><br/>" ), "<br>", html_entity_decode( trim( $matches[3][$key] ) ) ); |
856
|
|
|
$return['address'] = trim( strip_tags( $address, '<br>' ) ); |
857
|
|
|
break; |
858
|
|
|
case 'consultation number': |
859
|
|
|
$return['consultation'] = trim( strip_tags( $matches[3][$key] ) ); |
860
|
|
|
break; |
861
|
|
|
} |
862
|
|
|
} |
863
|
|
|
|
864
|
|
|
if ( !empty( $return ) ) { |
865
|
|
|
return $return; |
866
|
|
|
} |
867
|
|
|
} |
868
|
|
|
} |
869
|
|
|
|
870
|
|
|
return true; |
871
|
|
|
} else { |
872
|
|
|
return $result; |
873
|
|
|
} |
874
|
|
|
} |
875
|
|
|
|
876
|
|
|
public static function check_vat( $vat_number, $country_code = '' ) { |
877
|
|
|
$vat_name = getpaid_vat_name(); |
878
|
|
|
|
879
|
|
|
$return = array(); |
880
|
|
|
$return['valid'] = false; |
881
|
|
|
$return['message'] = wp_sprintf( __( '%s number not validated', 'invoicing' ), $vat_name ); |
882
|
|
|
|
883
|
|
|
if ( !wpinv_get_option( 'vat_offline_check' ) && !self::offline_check( $vat_number, $country_code ) ) { |
884
|
|
|
return $return; |
885
|
|
|
} |
886
|
|
|
|
887
|
|
|
$response = self::vies_check( $vat_number, $country_code ); |
888
|
|
|
|
889
|
|
|
if ( $response ) { |
890
|
|
|
$return['valid'] = true; |
891
|
|
|
|
892
|
|
|
if ( is_array( $response ) ) { |
893
|
|
|
$return['company'] = isset( $response['company'] ) ? $response['company'] : ''; |
894
|
|
|
$return['address'] = isset( $response['address'] ) ? $response['address'] : ''; |
895
|
|
|
$return['message'] = $return['company'] . '<br/>' . $return['address']; |
896
|
|
|
} |
897
|
|
|
} else { |
898
|
|
|
$return['valid'] = false; |
899
|
|
|
$return['message'] = wp_sprintf( __( 'Fail to validate the %s number: EU Commission VAT server (VIES) check fails.', 'invoicing' ), $vat_name ); |
900
|
|
|
} |
901
|
|
|
|
902
|
|
|
return $return; |
903
|
|
|
} |
904
|
|
|
|
905
|
|
|
public static function request_euvatrates( $group ) { |
906
|
|
|
$response = array(); |
907
|
|
|
$response['success'] = false; |
908
|
|
|
$response['error'] = null; |
909
|
|
|
$response['eurates'] = null; |
910
|
|
|
|
911
|
|
|
$euvatrates_url = 'https://euvatrates.com/rates.json'; |
912
|
|
|
$euvatrates_url = apply_filters( 'wpinv_euvatrates_url', $euvatrates_url ); |
913
|
|
|
$api_response = wp_remote_get( $euvatrates_url ); |
914
|
|
|
|
915
|
|
|
try { |
916
|
|
|
if ( is_wp_error( $api_response ) ) { |
917
|
|
|
$response['error'] = __( $api_response->get_error_message(), 'invoicing' ); |
918
|
|
|
} else { |
919
|
|
|
$body = json_decode( $api_response['body'] ); |
920
|
|
|
if ( isset( $body->rates ) ) { |
921
|
|
|
$rates = array(); |
922
|
|
|
|
923
|
|
|
foreach ( $body->rates as $country_code => $rate ) { |
924
|
|
|
$vat_rate = array(); |
925
|
|
|
$vat_rate['country'] = $rate->country; |
926
|
|
|
$vat_rate['standard'] = (float)$rate->standard_rate; |
927
|
|
|
$vat_rate['reduced'] = (float)$rate->reduced_rate; |
928
|
|
|
$vat_rate['superreduced'] = (float)$rate->super_reduced_rate; |
929
|
|
|
$vat_rate['parking'] = (float)$rate->parking_rate; |
930
|
|
|
|
931
|
|
|
if ( $group !== '' && in_array( $group, array( 'standard', 'reduced', 'superreduced', 'parking' ) ) ) { |
932
|
|
|
$vat_rate_group = array(); |
933
|
|
|
$vat_rate_group['country'] = $rate->country; |
934
|
|
|
$vat_rate_group[$group] = $vat_rate[$group]; |
935
|
|
|
|
936
|
|
|
$vat_rate = $vat_rate_group; |
937
|
|
|
} |
938
|
|
|
|
939
|
|
|
$rates[$country_code] = $vat_rate; |
940
|
|
|
} |
941
|
|
|
|
942
|
|
|
$response['success'] = true; |
943
|
|
|
$response['rates'] = apply_filters( 'wpinv_process_euvatrates', $rates, $api_response, $group ); |
944
|
|
|
} else { |
945
|
|
|
$response['error'] = __( 'No EU rates found!', 'invoicing' ); |
946
|
|
|
} |
947
|
|
|
} |
948
|
|
|
} catch ( Exception $e ) { |
949
|
|
|
$response['error'] = __( $e->getMessage(), 'invoicing' ); |
950
|
|
|
} |
951
|
|
|
|
952
|
|
|
return apply_filters( 'wpinv_response_euvatrates', $response, $group ); |
953
|
|
|
} |
954
|
|
|
|
955
|
|
|
public static function requires_vat( $requires_vat = false, $user_id = 0, $is_digital = null ) { |
956
|
|
|
global $wpi_item_id, $wpi_country; |
957
|
|
|
|
958
|
|
|
if ( !empty( $_POST['wpinv_country'] ) ) { |
959
|
|
|
$country_code = trim( $_POST['wpinv_country'] ); |
960
|
|
|
} else if ( !empty( $_POST['country'] ) ) { |
961
|
|
|
$country_code = trim( $_POST['country'] ); |
962
|
|
|
} else if ( !empty( $wpi_country ) ) { |
963
|
|
|
$country_code = $wpi_country; |
964
|
|
|
} else { |
965
|
|
|
$country_code = self::get_user_country( '', $user_id ); |
966
|
|
|
} |
967
|
|
|
|
968
|
|
|
if ( $is_digital === null && $wpi_item_id ) { |
969
|
|
|
$is_digital = $wpi_item_id ? self::item_has_digital_rule( $wpi_item_id ) : self::allow_vat_rules(); |
970
|
|
|
} |
971
|
|
|
|
972
|
|
|
if ( !empty( $country_code ) ) { |
973
|
|
|
$requires_vat = ( self::is_eu_state( $country_code ) && ( self::is_eu_state( wpinv_get_default_country() ) || $is_digital ) ) || ( self::is_gst_country( $country_code ) && self::is_gst_country( wpinv_get_default_country() ) ); |
|
|
|
|
974
|
|
|
} |
975
|
|
|
|
976
|
|
|
return apply_filters( 'wpinv_requires_vat', $requires_vat, $user_id ); |
977
|
|
|
} |
978
|
|
|
|
979
|
|
|
public static function tax_label( $label = '' ) { |
980
|
|
|
global $wpi_requires_vat; |
981
|
|
|
|
982
|
|
|
if ( !( $wpi_requires_vat !== 0 && $wpi_requires_vat ) ) { |
983
|
|
|
$wpi_requires_vat = self::requires_vat( 0, false ); |
984
|
|
|
} |
985
|
|
|
|
986
|
|
|
return $wpi_requires_vat ? __( self::get_vat_name(), 'invoicing' ) : ( $label ? $label : __( 'Tax', 'invoicing' ) ); |
|
|
|
|
987
|
|
|
} |
988
|
|
|
|
989
|
|
|
public static function standard_rates_label() { |
990
|
|
|
return __( 'Standard Rates', 'invoicing' ); |
991
|
|
|
} |
992
|
|
|
|
993
|
|
|
public static function get_rate_classes( $with_desc = false ) { |
994
|
|
|
$rate_classes_option = get_option( '_wpinv_vat_rate_classes', true ); |
995
|
|
|
$classes = maybe_unserialize( $rate_classes_option ); |
996
|
|
|
|
997
|
|
|
if ( empty( $classes ) || !is_array( $classes ) ) { |
998
|
|
|
$classes = array(); |
999
|
|
|
} |
1000
|
|
|
|
1001
|
|
|
$rate_classes = array(); |
1002
|
|
|
if ( !array_key_exists( '_standard', $classes ) ) { |
1003
|
|
|
if ( $with_desc ) { |
1004
|
|
|
$rate_classes['_standard'] = array( 'name' => self::standard_rates_label(), 'desc' => __( 'EU member states standard VAT rates', 'invoicing' ) ); |
1005
|
|
|
} else { |
1006
|
|
|
$rate_classes['_standard'] = self::standard_rates_label(); |
1007
|
|
|
} |
1008
|
|
|
} |
1009
|
|
|
|
1010
|
|
|
foreach ( $classes as $key => $class ) { |
1011
|
|
|
$name = !empty( $class['name'] ) ? __( $class['name'], 'invoicing' ) : $key; |
1012
|
|
|
$desc = !empty( $class['desc'] ) ? __( $class['desc'], 'invoicing' ) : ''; |
1013
|
|
|
|
1014
|
|
|
if ( $with_desc ) { |
1015
|
|
|
$rate_classes[$key] = array( 'name' => $name, 'desc' => $desc ); |
1016
|
|
|
} else { |
1017
|
|
|
$rate_classes[$key] = $name; |
1018
|
|
|
} |
1019
|
|
|
} |
1020
|
|
|
|
1021
|
|
|
return $rate_classes; |
1022
|
|
|
} |
1023
|
|
|
|
1024
|
|
|
public static function get_all_classes() { |
1025
|
|
|
$classes = self::get_rate_classes(); |
1026
|
|
|
$classes['_exempt'] = __( 'Exempt (0%)', 'invoicing' ); |
1027
|
|
|
|
1028
|
|
|
return apply_filters( 'wpinv_vat_get_all_classes', $classes ); |
1029
|
|
|
} |
1030
|
|
|
|
1031
|
|
|
public static function get_class_desc( $rate_class ) { |
1032
|
|
|
$rate_classes = self::get_rate_classes( true ); |
1033
|
|
|
|
1034
|
|
|
if ( !empty( $rate_classes ) && isset( $rate_classes[$rate_class] ) && isset( $rate_classes[$rate_class]['desc'] ) ) { |
1035
|
|
|
return $rate_classes[$rate_class]['desc']; |
1036
|
|
|
} |
1037
|
|
|
|
1038
|
|
|
return ''; |
1039
|
|
|
} |
1040
|
|
|
|
1041
|
|
|
public static function get_vat_groups() { |
1042
|
|
|
$vat_groups = array( |
1043
|
|
|
'standard' => 'Standard', |
1044
|
|
|
'reduced' => 'Reduced', |
1045
|
|
|
'superreduced' => 'Super Reduced', |
1046
|
|
|
'parking' => 'Parking', |
1047
|
|
|
'increased' => 'Increased' |
1048
|
|
|
); |
1049
|
|
|
|
1050
|
|
|
return apply_filters( 'wpinv_get_vat_groups', $vat_groups ); |
1051
|
|
|
} |
1052
|
|
|
|
1053
|
|
|
public static function get_rules() { |
1054
|
|
|
$vat_rules = array( |
1055
|
|
|
'digital' => __( 'Digital Product', 'invoicing' ), |
1056
|
|
|
'physical' => __( 'Physical Product', 'invoicing' ), |
1057
|
|
|
'_exempt' => __( 'Tax-Free Product', 'invoicing' ), |
1058
|
|
|
); |
1059
|
|
|
return apply_filters( 'wpinv_get_vat_rules', $vat_rules ); |
1060
|
|
|
} |
1061
|
|
|
|
1062
|
|
|
public static function get_vat_rates( $class ) { |
1063
|
|
|
if ( $class === '_standard' ) { |
1064
|
|
|
return wpinv_get_tax_rates(); |
1065
|
|
|
} |
1066
|
|
|
|
1067
|
|
|
$rates = self::get_non_standard_rates(); |
1068
|
|
|
|
1069
|
|
|
return array_key_exists( $class, $rates ) ? $rates[$class] : array(); |
1070
|
|
|
} |
1071
|
|
|
|
1072
|
|
|
public static function get_non_standard_rates() { |
1073
|
|
|
$option = get_option( 'wpinv_vat_rates', array()); |
1074
|
|
|
return is_array( $option ) ? $option : array(); |
1075
|
|
|
} |
1076
|
|
|
|
1077
|
|
|
public static function allow_vat_rules() { |
1078
|
|
|
return ( wpinv_use_taxes() && wpinv_get_option( 'apply_vat_rules' ) ? true : false ); |
1079
|
|
|
} |
1080
|
|
|
|
1081
|
|
|
public static function allow_vat_classes() { |
1082
|
|
|
return false; // TODO |
1083
|
|
|
return ( wpinv_get_option( 'vat_allow_classes' ) ? true : false ); |
|
|
|
|
1084
|
|
|
} |
1085
|
|
|
|
1086
|
|
|
public static function get_item_class( $postID ) { |
1087
|
|
|
$class = get_post_meta( $postID, '_wpinv_vat_class', true ); |
1088
|
|
|
|
1089
|
|
|
if ( empty( $class ) ) { |
1090
|
|
|
$class = '_standard'; |
1091
|
|
|
} |
1092
|
|
|
|
1093
|
|
|
return apply_filters( 'wpinv_get_item_vat_class', $class, $postID ); |
1094
|
|
|
} |
1095
|
|
|
|
1096
|
|
|
public static function item_class_label( $postID ) { |
1097
|
|
|
$vat_classes = self::get_all_classes(); |
1098
|
|
|
|
1099
|
|
|
$class = self::get_item_class( $postID ); |
1100
|
|
|
$class = isset( $vat_classes[$class] ) ? $vat_classes[$class] : __( $class, 'invoicing' ); |
1101
|
|
|
|
1102
|
|
|
return apply_filters( 'wpinv_item_class_label', $class, $postID ); |
1103
|
|
|
} |
1104
|
|
|
|
1105
|
|
|
public static function get_item_rule( $postID ) { |
1106
|
|
|
$rule_type = get_post_meta( $postID, '_wpinv_vat_rule', true ); |
1107
|
|
|
|
1108
|
|
|
if ( empty( $rule_type ) ) { |
1109
|
|
|
$rule_type = self::allow_vat_rules() ? 'digital' : 'physical'; |
1110
|
|
|
} |
1111
|
|
|
|
1112
|
|
|
return apply_filters( 'wpinv_item_get_vat_rule', $rule_type, $postID ); |
1113
|
|
|
} |
1114
|
|
|
|
1115
|
|
|
public static function item_rule_label( $postID ) { |
1116
|
|
|
$vat_rules = self::get_rules(); |
1117
|
|
|
$vat_rule = self::get_item_rule( $postID ); |
1118
|
|
|
$vat_rule = isset( $vat_rules[$vat_rule] ) ? $vat_rules[$vat_rule] : $vat_rule; |
1119
|
|
|
|
1120
|
|
|
return apply_filters( 'wpinv_item_rule_label', $vat_rule, $postID ); |
1121
|
|
|
} |
1122
|
|
|
|
1123
|
|
|
public static function item_has_digital_rule( $item_id = 0 ) { |
1124
|
|
|
return self::get_item_rule( $item_id ) == 'digital' ? true : false; |
1125
|
|
|
} |
1126
|
|
|
|
1127
|
|
|
public static function invoice_has_digital_rule( $invoice = 0 ) { |
1128
|
|
|
if ( !self::allow_vat_rules() ) { |
1129
|
|
|
return false; |
1130
|
|
|
} |
1131
|
|
|
|
1132
|
|
|
if ( empty( $invoice ) ) { |
1133
|
|
|
return true; |
1134
|
|
|
} |
1135
|
|
|
|
1136
|
|
|
if ( is_int( $invoice ) ) { |
1137
|
|
|
$invoice = new WPInv_Invoice( $invoice ); |
1138
|
|
|
} |
1139
|
|
|
|
1140
|
|
|
if ( !( is_object( $invoice ) && is_a( $invoice, 'WPInv_Invoice' ) ) ) { |
1141
|
|
|
return true; |
1142
|
|
|
} |
1143
|
|
|
|
1144
|
|
|
$cart_items = $invoice->get_cart_details(); |
1145
|
|
|
|
1146
|
|
|
if ( !empty( $cart_items ) ) { |
1147
|
|
|
$has_digital_rule = false; |
1148
|
|
|
|
1149
|
|
|
foreach ( $cart_items as $key => $item ) { |
1150
|
|
|
if ( self::item_has_digital_rule( $item['id'] ) ) { |
1151
|
|
|
$has_digital_rule = true; |
1152
|
|
|
break; |
1153
|
|
|
} |
1154
|
|
|
} |
1155
|
|
|
} else { |
1156
|
|
|
$has_digital_rule = true; |
1157
|
|
|
} |
1158
|
|
|
|
1159
|
|
|
return $has_digital_rule; |
1160
|
|
|
} |
1161
|
|
|
|
1162
|
|
|
public static function item_is_taxable( $item_id = 0, $country = false, $state = false ) { |
1163
|
|
|
if ( !wpinv_use_taxes() ) { |
1164
|
|
|
return false; |
1165
|
|
|
} |
1166
|
|
|
|
1167
|
|
|
$is_taxable = true; |
1168
|
|
|
|
1169
|
|
|
if ( !empty( $item_id ) && self::get_item_class( $item_id ) == '_exempt' ) { |
1170
|
|
|
$is_taxable = false; |
1171
|
|
|
} |
1172
|
|
|
|
1173
|
|
|
if ( !empty( $item_id ) && self::get_item_rule( $item_id ) == '_exempt' ) { |
1174
|
|
|
$is_taxable = false; |
1175
|
|
|
} |
1176
|
|
|
|
1177
|
|
|
return apply_filters( 'wpinv_item_is_taxable', $is_taxable, $item_id, $country , $state ); |
1178
|
|
|
} |
1179
|
|
|
|
1180
|
|
|
public static function find_rate( $country, $state, $rate, $class ) { |
1181
|
|
|
global $wpi_zero_tax; |
1182
|
|
|
|
1183
|
|
|
if ( $class === '_exempt' || $wpi_zero_tax ) { |
1184
|
|
|
return 0; |
1185
|
|
|
} |
1186
|
|
|
|
1187
|
|
|
$tax_rates = wpinv_get_tax_rates(); |
1188
|
|
|
|
1189
|
|
|
if ( $class !== '_standard' ) { |
1190
|
|
|
$class_rates = self::get_vat_rates( $class ); |
1191
|
|
|
|
1192
|
|
|
if ( is_array( $class_rates ) ) { |
1193
|
|
|
$indexed_class_rates = array(); |
1194
|
|
|
|
1195
|
|
|
foreach ( $class_rates as $key => $cr ) { |
1196
|
|
|
$indexed_class_rates[$cr['country']] = $cr; |
1197
|
|
|
} |
1198
|
|
|
|
1199
|
|
|
$tax_rates = array_map( function( $tr ) use( $indexed_class_rates ) { |
1200
|
|
|
$tr_country = $tr['country']; |
1201
|
|
|
if ( !isset( $indexed_class_rates[$tr_country] ) ) { |
1202
|
|
|
return $tr; |
1203
|
|
|
} |
1204
|
|
|
$icr = $indexed_class_rates[$tr_country]; |
1205
|
|
|
return ( empty( $icr['rate'] ) && $icr['rate'] !== '0' ) ? $tr : $icr; |
1206
|
|
|
|
1207
|
|
|
}, $tax_rates, $class_rates ); |
|
|
|
|
1208
|
|
|
} |
1209
|
|
|
} |
1210
|
|
|
|
1211
|
|
|
if ( !empty( $tax_rates ) ) { |
1212
|
|
|
foreach ( $tax_rates as $key => $tax_rate ) { |
1213
|
|
|
if ( $country != $tax_rate['country'] ) |
1214
|
|
|
continue; |
1215
|
|
|
|
1216
|
|
|
if ( !empty( $tax_rate['global'] ) ) { |
1217
|
|
|
if ( 0 !== $tax_rate['rate'] || !empty( $tax_rate['rate'] ) ) { |
1218
|
|
|
$rate = number_format( $tax_rate['rate'], 4 ); |
1219
|
|
|
} |
1220
|
|
|
} else { |
1221
|
|
|
if ( empty( $tax_rate['state'] ) || strtolower( $state ) != strtolower( $tax_rate['state'] ) ) |
1222
|
|
|
continue; |
1223
|
|
|
|
1224
|
|
|
$state_rate = $tax_rate['rate']; |
1225
|
|
|
if ( 0 !== $state_rate || !empty( $state_rate ) ) { |
1226
|
|
|
$rate = number_format( $state_rate, 4 ); |
1227
|
|
|
} |
1228
|
|
|
} |
1229
|
|
|
} |
1230
|
|
|
} |
1231
|
|
|
|
1232
|
|
|
return $rate; |
1233
|
|
|
} |
1234
|
|
|
|
1235
|
|
|
public static function get_rate( $rate = 1, $country = '', $state = '', $item_id = 0 ) { |
1236
|
|
|
global $wpinv_options, $wpi_item_id, $wpi_zero_tax; |
1237
|
|
|
|
1238
|
|
|
$item_id = $item_id > 0 ? $item_id : $wpi_item_id; |
1239
|
|
|
$allow_vat_classes = self::allow_vat_classes(); |
1240
|
|
|
$class = $item_id ? self::get_item_class( $item_id ) : '_standard'; |
1241
|
|
|
|
1242
|
|
|
if ( $class === '_exempt' || $wpi_zero_tax ) { |
1243
|
|
|
return 0; |
1244
|
|
|
} else if ( !$allow_vat_classes ) { |
|
|
|
|
1245
|
|
|
$class = '_standard'; |
1246
|
|
|
} |
1247
|
|
|
|
1248
|
|
|
if( !empty( $_POST['wpinv_country'] ) ) { |
1249
|
|
|
$post_country = $_POST['wpinv_country']; |
1250
|
|
|
} elseif( !empty( $_POST['wpinv_country'] ) ) { |
1251
|
|
|
$post_country = $_POST['wpinv_country']; |
1252
|
|
|
} elseif( !empty( $_POST['country'] ) ) { |
1253
|
|
|
$post_country = $_POST['country']; |
1254
|
|
|
} else { |
1255
|
|
|
$post_country = ''; |
1256
|
|
|
} |
1257
|
|
|
|
1258
|
|
|
$country = !empty( $post_country ) ? $post_country : wpinv_default_billing_country( $country ); |
1259
|
|
|
$base_country = wpinv_is_base_country( $country ); |
1260
|
|
|
|
1261
|
|
|
$requires_vat = self::requires_vat( 0, false ); |
1262
|
|
|
$is_digital = self::get_item_rule( $item_id ) == 'digital' ; |
1263
|
|
|
$rate = $requires_vat && isset( $wpinv_options['eu_fallback_rate'] ) ? $wpinv_options['eu_fallback_rate'] : $rate; |
1264
|
|
|
|
1265
|
|
|
if ( self::same_country_rule() == 'no' && $base_country ) { // Disable VAT to same country |
1266
|
|
|
$rate = 0; |
1267
|
|
|
} else if ( $requires_vat ) { |
1268
|
|
|
$vat_number = self::get_user_vat_number( '', 0, true ); |
1269
|
|
|
$vat_info = self::current_vat_data(); |
1270
|
|
|
|
1271
|
|
|
if ( is_array( $vat_info ) ) { |
1272
|
|
|
$vat_number = isset( $vat_info['number'] ) && !empty( $vat_info['valid'] ) ? $vat_info['number'] : ""; |
1273
|
|
|
} |
1274
|
|
|
|
1275
|
|
|
if ( $country == 'UK' ) { |
1276
|
|
|
$country = 'GB'; |
1277
|
|
|
} |
1278
|
|
|
|
1279
|
|
|
if ( !empty( $vat_number ) ) { |
1280
|
|
|
$rate = 0; |
1281
|
|
|
} else { |
1282
|
|
|
$rate = self::find_rate( $country, $state, $rate, $class ); // Fix if there are no tax rated and you try to pay an invoice it does not add the fallback tax rate |
1283
|
|
|
} |
1284
|
|
|
|
1285
|
|
|
if ( empty( $vat_number ) && !$is_digital ) { |
1286
|
|
|
if ( $base_country ) { |
1287
|
|
|
$rate = self::find_rate( $country, null, $rate, $class ); |
1288
|
|
|
} else { |
1289
|
|
|
if ( empty( $country ) && isset( $wpinv_options['eu_fallback_rate'] ) ) { |
1290
|
|
|
$rate = $wpinv_options['eu_fallback_rate']; |
1291
|
|
|
} else if( !empty( $country ) ) { |
1292
|
|
|
$rate = self::find_rate( $country, $state, $rate, $class ); |
1293
|
|
|
} |
1294
|
|
|
} |
1295
|
|
|
} else if ( empty( $vat_number ) || ( self::same_country_rule() == 'always' && $base_country ) ) { |
1296
|
|
|
if ( empty( $country ) && isset( $wpinv_options['eu_fallback_rate'] ) ) { |
1297
|
|
|
$rate = $wpinv_options['eu_fallback_rate']; |
1298
|
|
|
} else if( !empty( $country ) ) { |
1299
|
|
|
$rate = self::find_rate( $country, $state, $rate, $class ); |
1300
|
|
|
} |
1301
|
|
|
} |
1302
|
|
|
} else { |
1303
|
|
|
if ( $is_digital ) { |
1304
|
|
|
$ip_country_code = getpaid_get_ip_country(); |
1305
|
|
|
|
1306
|
|
|
if ( $ip_country_code && self::is_eu_state( $ip_country_code ) ) { |
1307
|
|
|
$rate = self::find_rate( $ip_country_code, '', 0, $class ); |
1308
|
|
|
} else { |
1309
|
|
|
$rate = self::find_rate( $country, $state, $rate, $class ); |
1310
|
|
|
} |
1311
|
|
|
} else { |
1312
|
|
|
$rate = self::find_rate( $country, $state, $rate, $class ); |
1313
|
|
|
} |
1314
|
|
|
} |
1315
|
|
|
|
1316
|
|
|
return $rate; |
1317
|
|
|
} |
1318
|
|
|
|
1319
|
|
|
public static function current_vat_data() { |
1320
|
|
|
return getpaid_session()->get( 'user_vat_data' ); |
1321
|
|
|
} |
1322
|
|
|
|
1323
|
|
|
public static function get_user_country( $country = '', $user_id = 0 ) { |
1324
|
|
|
$user_address = wpinv_get_user_address( $user_id, false ); |
1325
|
|
|
|
1326
|
|
|
$country = empty( $user_address ) || !isset( $user_address['country'] ) || empty( $user_address['country'] ) ? $country : $user_address['country']; |
1327
|
|
|
$result = apply_filters( 'wpinv_get_user_country', $country, $user_id ); |
1328
|
|
|
|
1329
|
|
|
if ( empty( $result ) ) { |
1330
|
|
|
$result = getpaid_get_ip_country(); |
1331
|
|
|
} |
1332
|
|
|
|
1333
|
|
|
return $result; |
1334
|
|
|
} |
1335
|
|
|
|
1336
|
|
|
public static function set_user_country( $country = '', $user_id = 0 ) { |
|
|
|
|
1337
|
|
|
global $wpi_userID; |
1338
|
|
|
|
1339
|
|
|
if ( empty($country) && !empty($wpi_userID) && get_current_user_id() != $wpi_userID ) { |
1340
|
|
|
$country = wpinv_get_default_country(); |
1341
|
|
|
} |
1342
|
|
|
|
1343
|
|
|
return $country; |
1344
|
|
|
} |
1345
|
|
|
|
1346
|
|
|
public static function get_user_vat_number( $vat_number = '', $user_id = 0, $is_valid = false ) { |
|
|
|
|
1347
|
|
|
global $wpi_current_id, $wpi_userID; |
1348
|
|
|
|
1349
|
|
|
if ( !empty( $_POST['new_user'] ) ) { |
1350
|
|
|
return ''; |
1351
|
|
|
} |
1352
|
|
|
|
1353
|
|
|
if ( empty( $user_id ) ) { |
1354
|
|
|
$user_id = !empty( $wpi_userID ) ? $wpi_userID : ( $wpi_current_id ? wpinv_get_user_id( $wpi_current_id ) : get_current_user_id() ); |
|
|
|
|
1355
|
|
|
} |
1356
|
|
|
|
1357
|
|
|
$vat_number = empty( $user_id ) ? '' : get_user_meta( $user_id, '_wpinv_vat_number', true ); |
1358
|
|
|
|
1359
|
|
|
/* TODO |
1360
|
|
|
if ( $is_valid && $vat_number ) { |
1361
|
|
|
$adddress_confirmed = empty( $user_id ) ? false : get_user_meta( $user_id, '_wpinv_adddress_confirmed', true ); |
1362
|
|
|
if ( !$adddress_confirmed ) { |
1363
|
|
|
$vat_number = ''; |
1364
|
|
|
} |
1365
|
|
|
} |
1366
|
|
|
*/ |
1367
|
|
|
|
1368
|
|
|
return apply_filters('wpinv_get_user_vat_number', $vat_number, $user_id, $is_valid ); |
1369
|
|
|
} |
1370
|
|
|
|
1371
|
|
|
public static function get_user_company( $company = '', $user_id = 0 ) { |
|
|
|
|
1372
|
|
|
global $wpi_current_id, $wpi_userID; |
1373
|
|
|
|
1374
|
|
|
if ( empty( $user_id ) ) { |
1375
|
|
|
$user_id = !empty( $wpi_userID ) ? $wpi_userID : ( $wpi_current_id ? wpinv_get_user_id( $wpi_current_id ) : get_current_user_id() ); |
|
|
|
|
1376
|
|
|
} |
1377
|
|
|
|
1378
|
|
|
$company = empty( $user_id ) ? "" : get_user_meta( $user_id, '_wpinv_company', true ); |
1379
|
|
|
|
1380
|
|
|
return apply_filters( 'wpinv_user_company', $company, $user_id ); |
1381
|
|
|
} |
1382
|
|
|
|
1383
|
|
|
public static function save_user_vat_details( $company = '', $vat_number = '' ) { |
1384
|
|
|
$save = apply_filters( 'wpinv_allow_save_user_vat_details', true ); |
1385
|
|
|
|
1386
|
|
|
if ( is_user_logged_in() && $save ) { |
1387
|
|
|
$user_id = get_current_user_id(); |
1388
|
|
|
|
1389
|
|
|
if ( !empty( $vat_number ) ) { |
1390
|
|
|
update_user_meta( $user_id, '_wpinv_vat_number', $vat_number ); |
1391
|
|
|
} else { |
1392
|
|
|
delete_user_meta( $user_id, '_wpinv_vat_number'); |
1393
|
|
|
} |
1394
|
|
|
|
1395
|
|
|
if ( !empty( $company ) ) { |
1396
|
|
|
update_user_meta( $user_id, '_wpinv_company', $company ); |
1397
|
|
|
} else { |
1398
|
|
|
delete_user_meta( $user_id, '_wpinv_company'); |
1399
|
|
|
delete_user_meta( $user_id, '_wpinv_vat_number'); |
1400
|
|
|
} |
1401
|
|
|
} |
1402
|
|
|
|
1403
|
|
|
do_action('wpinv_save_user_vat_details', $company, $vat_number); |
1404
|
|
|
} |
1405
|
|
|
|
1406
|
|
|
public static function ajax_vat_validate() { |
1407
|
|
|
global $wpinv_options; |
1408
|
|
|
|
1409
|
|
|
$response = array(); |
1410
|
|
|
$response['success'] = false; |
1411
|
|
|
|
1412
|
|
|
if ( empty( $_REQUEST['_wpi_nonce'] ) || ( !empty( $_REQUEST['_wpi_nonce'] ) && !wp_verify_nonce( $_REQUEST['_wpi_nonce'], 'vat_validation' ) ) ) { |
1413
|
|
|
$response['error'] = __( 'Invalid security nonce', 'invoicing' ); |
1414
|
|
|
wp_send_json( $response ); |
1415
|
|
|
} |
1416
|
|
|
|
1417
|
|
|
$vat_name = self::get_vat_name(); |
|
|
|
|
1418
|
|
|
|
1419
|
|
|
$company = !empty( $_POST['company'] ) ? sanitize_text_field( $_POST['company'] ) : ''; |
1420
|
|
|
$vat_number = !empty( $_POST['number'] ) ? sanitize_text_field( $_POST['number'] ) : ''; |
1421
|
|
|
|
1422
|
|
|
$vat_info = getpaid_session()->get( 'user_vat_data' ); |
1423
|
|
|
if ( !is_array( $vat_info ) || empty( $vat_info ) ) { |
1424
|
|
|
$vat_info = array( 'company'=> $company, 'number' => '', 'valid' => true ); |
1425
|
|
|
} |
1426
|
|
|
|
1427
|
|
|
if ( empty( $vat_number ) ) { |
1428
|
|
|
$response['error'] = wp_sprintf( __( 'Please enter your %s number!', 'invoicing' ), $vat_name ); |
1429
|
|
|
$vat_info['valid'] = false; |
1430
|
|
|
getpaid_session()->set( 'user_vat_data', $vat_info ); |
1431
|
|
|
wp_send_json( $response ); |
1432
|
|
|
} |
1433
|
|
|
|
1434
|
|
|
if ( empty( $company ) ) { |
1435
|
|
|
$vat_info['valid'] = false; |
1436
|
|
|
getpaid_session()->set( 'user_vat_data', $vat_info ); |
1437
|
|
|
|
1438
|
|
|
$response['error'] = __( 'Please enter your registered company name!', 'invoicing' ); |
1439
|
|
|
wp_send_json( $response ); |
1440
|
|
|
} |
1441
|
|
|
|
1442
|
|
|
if ( !empty( $wpinv_options['vat_vies_check'] ) ) { |
1443
|
|
|
if ( empty( $wpinv_options['vat_offline_check'] ) && !self::offline_check( $vat_number ) ) { |
1444
|
|
|
$vat_info['valid'] = false; |
1445
|
|
|
getpaid_session()->set( 'user_vat_data', $vat_info ); |
1446
|
|
|
|
1447
|
|
|
$response['error'] = wp_sprintf( __( '%s number not validated', 'invoicing' ), $vat_name ); |
1448
|
|
|
wp_send_json( $response ); |
1449
|
|
|
} |
1450
|
|
|
|
1451
|
|
|
$response['success'] = true; |
1452
|
|
|
$response['message'] = wp_sprintf( __( '%s number validated', 'invoicing' ), $vat_name ); |
1453
|
|
|
} else { |
1454
|
|
|
$result = self::check_vat( $vat_number ); |
1455
|
|
|
|
1456
|
|
|
if ( empty( $result['valid'] ) ) { |
1457
|
|
|
$response['error'] = $result['message']; |
1458
|
|
|
wp_send_json( $response ); |
1459
|
|
|
} |
1460
|
|
|
|
1461
|
|
|
$vies_company = !empty( $result['company'] ) ? $result['company'] : ''; |
1462
|
|
|
$vies_company = apply_filters( 'wpinv_vies_company_name', $vies_company ); |
1463
|
|
|
|
1464
|
|
|
$valid_company = $vies_company && $company && ( $vies_company == '---' || strcasecmp( trim( $vies_company ), trim( $company ) ) == 0 ) ? true : false; |
1465
|
|
|
|
1466
|
|
|
if ( !empty( $wpinv_options['vat_disable_company_name_check'] ) || $valid_company ) { |
1467
|
|
|
$response['success'] = true; |
1468
|
|
|
$response['message'] = wp_sprintf( __( '%s number validated', 'invoicing' ), $vat_name ); |
1469
|
|
|
} else { |
1470
|
|
|
$vat_info['valid'] = false; |
1471
|
|
|
getpaid_session()->set( 'user_vat_data', $vat_info ); |
1472
|
|
|
|
1473
|
|
|
$response['success'] = false; |
1474
|
|
|
$response['message'] = wp_sprintf( __( 'The company name associated with the %s number provided is not the same as the company name provided.', 'invoicing' ), $vat_name ); |
1475
|
|
|
wp_send_json( $response ); |
1476
|
|
|
} |
1477
|
|
|
} |
1478
|
|
|
|
1479
|
|
|
wp_send_json( $response ); |
1480
|
|
|
} |
1481
|
|
|
|
1482
|
|
|
/** |
1483
|
|
|
* Validates a vat number. |
1484
|
|
|
* |
1485
|
|
|
* @return string |
1486
|
|
|
*/ |
1487
|
|
|
public static function validate_vat_number( $vat_number, $company, $country ) { |
1488
|
|
|
global $wpinv_options; |
1489
|
|
|
|
1490
|
|
|
// If we are not checking the vat number via view... |
1491
|
|
|
if ( ! empty( $wpinv_options['vat_vies_check'] ) ) { |
1492
|
|
|
|
1493
|
|
|
// Try validating via regex. |
1494
|
|
|
if ( empty( $wpinv_options['vat_offline_check'] ) && ! self::offline_check( $vat_number, $country ) ) { |
1495
|
|
|
return wp_sprintf( |
1496
|
|
|
__( 'Your %s number is invalid', 'invoicing' ), |
1497
|
|
|
getpaid_vat_name() |
1498
|
|
|
); |
1499
|
|
|
} |
1500
|
|
|
|
1501
|
|
|
return false; |
|
|
|
|
1502
|
|
|
} |
1503
|
|
|
|
1504
|
|
|
// Validate the vat number. |
1505
|
|
|
$result = self::check_vat( $vat_number, $country ); |
1506
|
|
|
|
1507
|
|
|
if ( empty( $result['valid'] ) ) { |
1508
|
|
|
return wp_sprintf( |
1509
|
|
|
__( 'Failed to validate the %s number via EU Commission VAT server (VIES).', 'invoicing' ), |
1510
|
|
|
getpaid_vat_name() |
1511
|
|
|
); |
1512
|
|
|
} |
1513
|
|
|
|
1514
|
|
|
// Validate the company. |
1515
|
|
|
$vies_company = ! empty( $result['company'] ) ? $result['company'] : ''; |
1516
|
|
|
$vies_company = apply_filters( 'wpinv_vies_company_name', $vies_company ); |
1517
|
|
|
$valid_company = $vies_company && $company && ( $vies_company == '---' || strcasecmp( trim( $vies_company ), trim( $company ) ) == 0 ) ? true : false; |
1518
|
|
|
|
1519
|
|
|
if ( ! $valid_company && ! empty( $wpinv_options['vat_disable_company_name_check'] ) ) { |
1520
|
|
|
return wp_sprintf( |
1521
|
|
|
__( 'The company name associated with the %s number provided is not the same as the company name provided.', 'invoicing' ), |
1522
|
|
|
getpaid_vat_name() |
1523
|
|
|
); |
1524
|
|
|
} |
1525
|
|
|
|
1526
|
|
|
return true; |
|
|
|
|
1527
|
|
|
} |
1528
|
|
|
|
1529
|
|
|
} |
1530
|
|
|
|
1531
|
|
|
|