Rendre le numéro de TVA obligatoire si société renseignée sur PrestaShop
Comment rendre le champ TVA intracommunautaire obligatoire conditionnellement quand une société est saisie sur PrestaShop 1.6, 1.7 et 8.x. Override propre et validation.
En bref : Pour rendre le numéro de TVA obligatoire quand une société est renseignée, il faut ajouter une validation conditionnelle dans les contrôleurs AuthController et AddressController (PS 1.6 via override) ou via un module avec le hook actionValidateCustomerAddressForm (PS 1.7+/8.x). Ne jamais modifier la classe Address.php pour cela.
Le problème : TVA facultative même quand une société est renseignée
Par défaut, PrestaShop ne rend jamais le numéro de TVA intracommunautaire obligatoire. Que le client saisisse ou non un nom de société, le champ reste optionnel. C'est un vrai problème pour les marchands B2B qui ont besoin du numéro de TVA pour établir des factures conformes, appliquer l'autoliquidation ou simplement vérifier la légitimité d'un achat professionnel.
La logique métier attendue est simple : si le client renseigne un nom de société, alors le numéro de TVA intracommunautaire doit devenir obligatoire.
Comprendre l'architecture des formulaires d'adresse
Avant de modifier quoi que ce soit, il faut comprendre que la validation de l'adresse intervient à deux endroits distincts dans PrestaShop :
- **À l'inscription** — Le contrôleur `AuthController` gère la soumission du formulaire de création de compte (méthode `processSubmitAccount()`)
- **À l'ajout/modification d'adresse** — Le contrôleur `AddressController` gère le carnet d'adresses (méthode `processSubmitAddress()`)
Si vous ne modifiez qu'un seul de ces deux contrôleurs, la validation sera incomplète : un client pourra contourner l'obligation en ajoutant son adresse professionnelle après l'inscription.
Le module European VAT Number
PrestaShop embarque un module natif appelé European VAT Number (anciennement vatnumber, renommé en module plus complet sur les versions récentes). Ce module ajoute le champ TVA dans les formulaires d'adresse et peut effectuer une vérification VIES. Cependant, il ne gère pas la logique de champ conditionnel obligatoire. C'est donc une personnalisation à implémenter côté contrôleur.
Assurez-vous que ce module est bien installé et activé avant de poursuivre.
Solution pour PrestaShop 1.6
Sur PrestaShop 1.6, la méthode la plus propre consiste à créer des overrides des deux contrôleurs front-office. Évitez absolument de modifier les fichiers core directement : chaque mise à jour écraserait vos modifications.
Override de AuthController
Créez le fichier override/controllers/front/AuthController.php :
<?php
class AuthController extends AuthControllerCore
{
protected function processSubmitAccount()
{
// Appel de la méthode parente
parent::processSubmitAccount();
// Vérification TVA conditionnelle : obligatoire si société renseignée
if (!empty(Tools::getValue('company'))) {
$vatNumber = Tools::getValue('vat_number');
if (empty($vatNumber)) {
$this->errors[] = Tools::displayError(
'Le numéro de TVA intracommunautaire est obligatoire pour les professionnels.'
);
}
}
}
}
Override de AddressController
Créez le fichier override/controllers/front/AddressController.php :
<?php
class AddressController extends AddressControllerCore
{
protected function processSubmitAddress()
{
// Vérification TVA conditionnelle avant le traitement standard
$address = new Address();
$address->company = Tools::getValue('company');
if (!empty($address->company)) {
$vatNumber = Tools::getValue('vat_number');
if (empty($vatNumber)) {
$this->errors[] = Tools::displayError(
'Le numéro de TVA intracommunautaire est obligatoire pour les professionnels.'
);
}
}
// Si pas d'erreur, on laisse le contrôleur parent traiter l'adresse
if (empty($this->errors)) {
parent::processSubmitAddress();
}
}
}
Important : Après avoir créé ces fichiers, supprimez le cache des classes :
rm -f var/cache/class_index.php # PS 1.6
Solution pour PrestaShop 1.7 et 8.x
À partir de PrestaShop 1.7, l'architecture des formulaires a été entièrement repensée avec le système de Form Builders basé sur Symfony. Les overrides de contrôleurs front restent possibles, mais la méthode recommandée passe par un module avec hook.
Approche recommandée : module avec validation par hook
Créez un module ac_vatRequired qui écoute le hook actionValidateCustomerAddressForm :
<?php
// modules/ac_vatrequired/ac_vatrequired.php
use PrestaShop\PrestaShop\Core\Form\FormHandlerInterface;
class Ac_VatRequired extends Module
{
public function __construct()
{
$this->name = 'ac_vatrequired';
$this->version = '1.0.0';
$this->author = 'Alexandre Carette';
$this->tab = 'billing_invoicing';
$this->need_instance = 0;
$this->ps_versions_compliancy = ['min' => '1.7.0.0', 'max' => '8.99.99'];
parent::__construct();
$this->displayName = $this->l('TVA obligatoire si société');
$this->description = $this->l('Rend le numéro de TVA obligatoire quand une société est renseignée.');
}
public function install()
{
return parent::install()
&& $this->registerHook('actionValidateCustomerAddressForm');
}
/**
* Hook de validation du formulaire d'adresse (PS 1.7+)
*/
public function hookActionValidateCustomerAddressForm(array $params)
{
/** @var PrestaShop\PrestaShop\Core\Domain\Address\ValueObject\Address $form */
$form = $params['form'];
$company = $form->getField('company')->getValue();
$vatNumber = $form->getField('vat_number')->getValue();
if (!empty($company) && empty($vatNumber)) {
$form->getField('vat_number')->addError(
$this->l('Le numéro de TVA intracommunautaire est obligatoire pour les professionnels.')
);
}
}
}
Vérification côté template (optionnel)
Pour améliorer l'expérience utilisateur, vous pouvez ajouter une validation JavaScript côté front qui affiche dynamiquement l'astérisque d'obligation quand le champ société est rempli :
// views/js/ac_vatrequired.js
document.addEventListener('DOMContentLoaded', function () {
const companyField = document.querySelector('input[name="company"]');
const vatGroup = document.querySelector('input[name="vat_number"]')?.closest('.form-group');
const vatLabel = vatGroup?.querySelector('label');
if (!companyField || !vatGroup) return;
function toggleVatRequired() {
const isCompany = companyField.value.trim() !== '';
const vatInput = vatGroup.querySelector('input[name="vat_number"]');
if (isCompany) {
vatInput.setAttribute('required', 'required');
if (vatLabel && !vatLabel.textContent.includes('*')) {
vatLabel.textContent += ' *';
}
} else {
vatInput.removeAttribute('required');
if (vatLabel) {
vatLabel.textContent = vatLabel.textContent.replace(' *', '');
}
}
}
companyField.addEventListener('input', toggleVatRequired);
toggleVatRequired();
});
Le piège de la définition du champ dans la classe Address
Dans la classe Address.php, le champ vat_number est défini ainsi :
'vat_number' => array('type' => self::TYPE_STRING, 'validate' => 'isGenericName'),
Notez qu'il n'y a pas de clé required' => true. C'est normal : la classe Address gère la définition statique du champ, pas sa logique conditionnelle. N'ajoutez surtout pas 'required' => true ici, car cela rendrait le numéro de TVA obligatoire pour tous les clients, y compris les particuliers. La validation conditionnelle doit rester dans le contrôleur ou le module.
Vérification VIES : aller plus loin
Rendre le champ obligatoire c'est bien, mais valider que le numéro est réel c'est mieux. PrestaShop 8.x intègre nativement la vérification via le service VIES de la Commission européenne. Si vous utilisez une version antérieure ou souhaitez une validation plus robuste :
/**
* Vérifie un numéro de TVA intracommunautaire via VIES
*/
function checkVatVies(string $vatNumber): bool
{
$vatNumber = str_replace([' ', '.', '-'], '', strtoupper($vatNumber));
$countryCode = substr($vatNumber, 0, 2);
$number = substr($vatNumber, 2);
try {
$client = new SoapClient('https://ec.europa.eu/taxation_customs/vies/checkVatService.wsdl');
$result = $client->checkVat([
'countryCode' => $countryCode,
'vatNumber' => $number,
]);
return (bool) $result->valid;
} catch (SoapFault $e) {
// Le service VIES peut être temporairement indisponible
// En cas d'erreur, on accepte le numéro et on log l'incident
PrestaShopLogger::addLog(
'VIES check failed: ' . $e->getMessage(),
2,
null,
'Address'
);
return true;
}
}
Récapitulatif des fichiers à créer ou modifier
Règle d'or : ne modifiez jamais directement les fichiers du core PrestaShop. Utilisez le système d'overrides (PS 1.6) ou les hooks modules (PS 1.7+/8.x) pour garantir la pérennité de vos modifications lors des mises à jour.
Questions fréquentes
Tout ce que vous devez savoir sur ce sujet.
Un projet PrestaShop ?
Discutons-en directement.
193 projets livrés
Lire sur le blog

Alexandre Carette
Expert PrestaShop & Architecture E-commerce
Développeur PrestaShop depuis 2014, 193 projets livrés. Je conçois des architectures headless Nuxt + PrestaShop et des outils d'automatisation IA pour les e-commerçants.