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_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.
|
||||
CONST INTRACOMMUNITY_EXEMPTION_TEXTS = [
|
||||
'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;
|
||||
|
||||
use Websmid\VatCheck\Config\Config;
|
||||
use Websmid\VatCheck\Model\EuCountryAllowList;
|
||||
use Configuration;
|
||||
use Tools;
|
||||
use HelperForm;
|
||||
use Context;
|
||||
use Country;
|
||||
|
||||
trait SettingsForm
|
||||
{
|
||||
@@ -31,6 +33,15 @@ trait SettingsForm
|
||||
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()
|
||||
@@ -77,8 +88,35 @@ trait SettingsForm
|
||||
null,
|
||||
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()
|
||||
{
|
||||
@@ -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' => [
|
||||
'title' => $this->trans('Save', [], 'Admin.Actions'),
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace Websmid\VatCheck\Module\Front;
|
||||
|
||||
use Websmid\VatCheck\TaxManager\CacheTaxManager;
|
||||
use Websmid\VatCheck\Model\VatNumber;
|
||||
use Websmid\VatCheck\Model\EuCountryAllowList;
|
||||
use Websmid\VatCheck\Config\Config;
|
||||
use Address;
|
||||
use Configuration;
|
||||
@@ -27,7 +28,7 @@ trait FrontHooks
|
||||
$countryIso = (string)Country::getIsoById((string)$form->getValue('id_country'));
|
||||
$vatNumber = new VatNumber($vatNumber, $countryIso);
|
||||
|
||||
if( $vatNumber->isNotEuIso() ){
|
||||
if( $vatNumber->isNotEuIso() || !EuCountryAllowList::isEnabled($countryIso) ){
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Websmid\VatCheck\Module;
|
||||
|
||||
use Websmid\VatCheck\Config\Config;
|
||||
use Websmid\VatCheck\Model\EuCountryAllowList;
|
||||
use Db;
|
||||
use Configuration;
|
||||
|
||||
@@ -39,6 +40,13 @@ trait Install
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Configuration::updateValue(
|
||||
Config::EU_COUNTRIES_CONFIG_KEY,
|
||||
json_encode(EuCountryAllowList::getAllSupportedIsoCodes())
|
||||
)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ use Configuration;
|
||||
use Context;
|
||||
use Websmid\VatCheck\Model\VatCache;
|
||||
use Websmid\VatCheck\Model\VatNumber;
|
||||
use Websmid\VatCheck\Model\EuCountryAllowList;
|
||||
use Websmid\VatCheck\Adapter\EuValidatorAdapter;
|
||||
|
||||
class CacheTaxManager implements TaxManagerInterface
|
||||
@@ -27,7 +28,7 @@ class CacheTaxManager implements TaxManagerInterface
|
||||
}
|
||||
|
||||
$isoCode = Country::getIsoById((int)$address->id_country);
|
||||
if( !array_key_exists($isoCode, VatNumber::$euIso) ){
|
||||
if( !EuCountryAllowList::isEnabled($isoCode) ){
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<?php
|
||||
|
||||
use Websmid\VatCheck\Config\Config;
|
||||
use Websmid\VatCheck\Model\EuCountryAllowList;
|
||||
|
||||
if (!defined('_PS_VERSION_')) {
|
||||
exit;
|
||||
@@ -12,5 +13,14 @@ function upgrade_module_1_0_3($module)
|
||||
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