feat(main): Add configurable EU country allow-list
This commit is contained in:
@@ -36,6 +36,11 @@ class Config
|
|||||||
CONST VALIDATE_COMPANY_CONFIG_KEY = 'WS_VATCHECK_VALIDATE_COMPANY';
|
CONST VALIDATE_COMPANY_CONFIG_KEY = 'WS_VATCHECK_VALIDATE_COMPANY';
|
||||||
CONST VALIDATE_COMPANY_DEFAULT = false;
|
CONST VALIDATE_COMPANY_DEFAULT = false;
|
||||||
|
|
||||||
|
// Configuration key holding the admin-selected list of EU countries allowed
|
||||||
|
// to order VAT-free (JSON-encoded array of ISO codes). Absent/empty means
|
||||||
|
// "all countries VatNumber::$euIso supports" — see EuCountryAllowList.
|
||||||
|
CONST EU_COUNTRIES_CONFIG_KEY = 'WS_VATCHECK_EU_COUNTRIES';
|
||||||
|
|
||||||
// Article 39bis W.BTW intra-community exemption notice, per invoice language.
|
// Article 39bis W.BTW intra-community exemption notice, per invoice language.
|
||||||
CONST INTRACOMMUNITY_EXEMPTION_TEXTS = [
|
CONST INTRACOMMUNITY_EXEMPTION_TEXTS = [
|
||||||
'nl' => 'Vrijgestelde intracommunautaire levering – artikel 39bis W.BTW',
|
'nl' => 'Vrijgestelde intracommunautaire levering – artikel 39bis W.BTW',
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Websmid\VatCheck\Model;
|
||||||
|
|
||||||
|
use Websmid\VatCheck\Config\Config;
|
||||||
|
use Configuration;
|
||||||
|
|
||||||
|
class EuCountryAllowList
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Every ISO code VatNumber knows a VAT prefix/format for — the maximum
|
||||||
|
* possible set an admin could enable.
|
||||||
|
*/
|
||||||
|
public static function getAllSupportedIsoCodes(): array
|
||||||
|
{
|
||||||
|
return array_keys(VatNumber::$euIso);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Falls back to "all supported countries" when nothing has been configured
|
||||||
|
* yet, so a fresh install/upgrade doesn't silently narrow existing behavior.
|
||||||
|
* Intersects against the supported set so a stale stored code can never
|
||||||
|
* make it back out.
|
||||||
|
*/
|
||||||
|
public static function getEnabledIsoCodes(): array
|
||||||
|
{
|
||||||
|
$stored = json_decode((string) Configuration::get(Config::EU_COUNTRIES_CONFIG_KEY), true);
|
||||||
|
|
||||||
|
if (empty($stored) || !is_array($stored)) {
|
||||||
|
return self::getAllSupportedIsoCodes();
|
||||||
|
}
|
||||||
|
|
||||||
|
return array_values(array_intersect($stored, self::getAllSupportedIsoCodes()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function isEnabled(string $isoCode): bool
|
||||||
|
{
|
||||||
|
return in_array($isoCode, self::getEnabledIsoCodes(), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,10 +3,12 @@
|
|||||||
namespace Websmid\VatCheck\Module\Admin;
|
namespace Websmid\VatCheck\Module\Admin;
|
||||||
|
|
||||||
use Websmid\VatCheck\Config\Config;
|
use Websmid\VatCheck\Config\Config;
|
||||||
|
use Websmid\VatCheck\Model\EuCountryAllowList;
|
||||||
use Configuration;
|
use Configuration;
|
||||||
use Tools;
|
use Tools;
|
||||||
use HelperForm;
|
use HelperForm;
|
||||||
use Context;
|
use Context;
|
||||||
|
use Country;
|
||||||
|
|
||||||
trait SettingsForm
|
trait SettingsForm
|
||||||
{
|
{
|
||||||
@@ -31,6 +33,15 @@ trait SettingsForm
|
|||||||
Config::VALIDATE_COMPANY_CONFIG_KEY,
|
Config::VALIDATE_COMPANY_CONFIG_KEY,
|
||||||
(bool) Tools::getValue(Config::VALIDATE_COMPANY_CONFIG_KEY)
|
(bool) Tools::getValue(Config::VALIDATE_COMPANY_CONFIG_KEY)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
$enabledIsoCodes = [];
|
||||||
|
foreach (EuCountryAllowList::getAllSupportedIsoCodes() as $isoCode) {
|
||||||
|
if (Tools::getValue(Config::EU_COUNTRIES_CONFIG_KEY . '_' . $isoCode)) {
|
||||||
|
$enabledIsoCodes[] = $isoCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Configuration::updateValue(Config::EU_COUNTRIES_CONFIG_KEY, json_encode($enabledIsoCodes));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function renderSettingsForm()
|
private function renderSettingsForm()
|
||||||
@@ -77,8 +88,35 @@ trait SettingsForm
|
|||||||
null,
|
null,
|
||||||
Config::VALIDATE_COMPANY_DEFAULT
|
Config::VALIDATE_COMPANY_DEFAULT
|
||||||
),
|
),
|
||||||
|
] + $this->getEnabledCountriesFormValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getEnabledCountriesFormValues()
|
||||||
|
{
|
||||||
|
$values = [];
|
||||||
|
foreach (EuCountryAllowList::getEnabledIsoCodes() as $isoCode) {
|
||||||
|
$values[Config::EU_COUNTRIES_CONFIG_KEY . '_' . $isoCode] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $values;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getCountryChoices()
|
||||||
|
{
|
||||||
|
$supported = EuCountryAllowList::getAllSupportedIsoCodes();
|
||||||
|
$choices = [];
|
||||||
|
|
||||||
|
foreach (Country::getCountries(Context::getContext()->language->id) as $country) {
|
||||||
|
if (in_array($country['iso_code'], $supported, true)) {
|
||||||
|
$choices[] = [
|
||||||
|
'id' => $country['iso_code'],
|
||||||
|
'name' => $country['name'] . ' (' . $country['iso_code'] . ')',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $choices;
|
||||||
|
}
|
||||||
|
|
||||||
private function getSettingsFormStructure()
|
private function getSettingsFormStructure()
|
||||||
{
|
{
|
||||||
@@ -132,6 +170,23 @@ trait SettingsForm
|
|||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'type' => 'checkbox',
|
||||||
|
'label' => $this->trans('Enabled EU countries', [], 'Modules.Ws_VatCheck.Admin'),
|
||||||
|
'name' => Config::EU_COUNTRIES_CONFIG_KEY,
|
||||||
|
'multiple' => true,
|
||||||
|
'desc' => $this->trans(
|
||||||
|
'Countries a customer can order VAT-free from with a valid VAT number.',
|
||||||
|
[],
|
||||||
|
'Modules.Ws_VatCheck.Admin'
|
||||||
|
),
|
||||||
|
'values' => [
|
||||||
|
'query' => $this->getCountryChoices(),
|
||||||
|
'id' => 'id',
|
||||||
|
'name' => 'name',
|
||||||
|
'value' => 'id',
|
||||||
|
],
|
||||||
|
],
|
||||||
],
|
],
|
||||||
'submit' => [
|
'submit' => [
|
||||||
'title' => $this->trans('Save', [], 'Admin.Actions'),
|
'title' => $this->trans('Save', [], 'Admin.Actions'),
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ namespace Websmid\VatCheck\Module\Front;
|
|||||||
|
|
||||||
use Websmid\VatCheck\TaxManager\CacheTaxManager;
|
use Websmid\VatCheck\TaxManager\CacheTaxManager;
|
||||||
use Websmid\VatCheck\Model\VatNumber;
|
use Websmid\VatCheck\Model\VatNumber;
|
||||||
|
use Websmid\VatCheck\Model\EuCountryAllowList;
|
||||||
use Websmid\VatCheck\Config\Config;
|
use Websmid\VatCheck\Config\Config;
|
||||||
use Address;
|
use Address;
|
||||||
use Configuration;
|
use Configuration;
|
||||||
@@ -27,7 +28,7 @@ trait FrontHooks
|
|||||||
$countryIso = (string)Country::getIsoById((string)$form->getValue('id_country'));
|
$countryIso = (string)Country::getIsoById((string)$form->getValue('id_country'));
|
||||||
$vatNumber = new VatNumber($vatNumber, $countryIso);
|
$vatNumber = new VatNumber($vatNumber, $countryIso);
|
||||||
|
|
||||||
if( $vatNumber->isNotEuIso() ){
|
if( $vatNumber->isNotEuIso() || !EuCountryAllowList::isEnabled($countryIso) ){
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
namespace Websmid\VatCheck\Module;
|
namespace Websmid\VatCheck\Module;
|
||||||
|
|
||||||
use Websmid\VatCheck\Config\Config;
|
use Websmid\VatCheck\Config\Config;
|
||||||
|
use Websmid\VatCheck\Model\EuCountryAllowList;
|
||||||
use Db;
|
use Db;
|
||||||
use Configuration;
|
use Configuration;
|
||||||
|
|
||||||
@@ -39,6 +40,13 @@ trait Install
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!Configuration::updateValue(
|
||||||
|
Config::EU_COUNTRIES_CONFIG_KEY,
|
||||||
|
json_encode(EuCountryAllowList::getAllSupportedIsoCodes())
|
||||||
|
)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use Configuration;
|
|||||||
use Context;
|
use Context;
|
||||||
use Websmid\VatCheck\Model\VatCache;
|
use Websmid\VatCheck\Model\VatCache;
|
||||||
use Websmid\VatCheck\Model\VatNumber;
|
use Websmid\VatCheck\Model\VatNumber;
|
||||||
|
use Websmid\VatCheck\Model\EuCountryAllowList;
|
||||||
use Websmid\VatCheck\Adapter\EuValidatorAdapter;
|
use Websmid\VatCheck\Adapter\EuValidatorAdapter;
|
||||||
|
|
||||||
class CacheTaxManager implements TaxManagerInterface
|
class CacheTaxManager implements TaxManagerInterface
|
||||||
@@ -27,7 +28,7 @@ class CacheTaxManager implements TaxManagerInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
$isoCode = Country::getIsoById((int)$address->id_country);
|
$isoCode = Country::getIsoById((int)$address->id_country);
|
||||||
if( !array_key_exists($isoCode, VatNumber::$euIso) ){
|
if( !EuCountryAllowList::isEnabled($isoCode) ){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
use Websmid\VatCheck\Config\Config;
|
use Websmid\VatCheck\Config\Config;
|
||||||
|
use Websmid\VatCheck\Model\EuCountryAllowList;
|
||||||
|
|
||||||
if (!defined('_PS_VERSION_')) {
|
if (!defined('_PS_VERSION_')) {
|
||||||
exit;
|
exit;
|
||||||
@@ -12,5 +13,14 @@ function upgrade_module_1_0_3($module)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Configuration::updateValue(Config::VALIDATE_COMPANY_CONFIG_KEY, Config::VALIDATE_COMPANY_DEFAULT);
|
if (!Configuration::updateValue(Config::VALIDATE_COMPANY_CONFIG_KEY, Config::VALIDATE_COMPANY_DEFAULT)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All countries enabled by default, so upgrading doesn't silently narrow
|
||||||
|
// exemption eligibility for a shop already relying on the old behavior.
|
||||||
|
return Configuration::updateValue(
|
||||||
|
Config::EU_COUNTRIES_CONFIG_KEY,
|
||||||
|
json_encode(EuCountryAllowList::getAllSupportedIsoCodes())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user