L’import ERP vers Shopware ne retrouve plus la taxe d’un produit, alors que le taux envoyé existe bien dans le catalogue. Ce blocage retarde la mise à jour du catalogue et déclenche des vérifications manuelles côté back-office. Une seconde fiche de taxe porte exactement la même valeur. Avec le résolveur tax.tax_rate de la Sync API, cette situation est volontairement laissée sans identifiant résolu : le taux est un critère de recherche qui ne désigne pas nécessairement une taxe unique.
Le risque est de corriger le taux envoyé alors que l’identité recherchée reste indécidable. Le bon arbitrage consiste à identifier la taxe métier attendue, puis à décider si la résolution par taux reste adaptée. Prendre le premier résultat ou supprimer une fiche pour débloquer l’import change le référentiel sans expliquer le choix. Un accompagnement en intégration API doit rendre cette correspondance explicite entre code fiscal ERP, taux numérique et identifiant Shopware, avec une reprise limitée aux produits réellement concernés.
Le cas pratique exécute le véritable TaxRateFkResolver de Shopware 6.7.15.1 avec Doctrine DBAL et une base SQLite en mémoire. Il compare une taxe unique, deux taxes au même taux et une référence absente. Ce témoin local vérifie la résolution de références ; il n’envoie aucun lot à Shopware, ne modifie aucun produit réel et ne certifie ni le calcul fiscal ni le comportement complet d’un serveur MySQL.
Ce diagnostic s’adresse aux équipes qui veulent connecter Shopware à leur ERP et à leurs applications métier, particulièrement lorsqu’un import auparavant accepté se bloque après une évolution du référentiel. La version publiée et la documentation utilisées ont été vérifiées en octobre 2026. La question à résoudre est précise : quelle identité la donnée source permet-elle réellement de choisir ?
Pour qui : le taux existe mais le produit reste sans correspondance
Isoler la référence de taxe dans le lot produit
Une ligne ERP peut contenir un code de taxe, un taux et une référence article. Ces trois informations n’ont pas le même rôle. Le code de taxe peut exprimer une distinction conservée dans votre système de gestion ; le taux seul réduit cette information à une valeur numérique. Avant de modifier le connecteur, retrouvez la ligne source, le produit visé et le champ taxId effectivement préparé dans le payload de synchronisation.
Le symptôme devient trompeur lorsque l’équipe constate simplement « le taux existe ». Deux fiches Shopware peuvent satisfaire ce contrôle tout en laissant le résolveur incapable de choisir. Le support a besoin du nombre de correspondances et de leurs identifiants, pas seulement d’une capture de l’écran des taxes. Cette distinction évite de classer une ambiguïté du référentiel comme une panne de disponibilité de l’API.
Délimiter ce que le diagnostic peut expliquer
Le scénario traite exclusivement les objets de résolution placés dans une demande Sync compatible avec la version installée. Il ne couvre pas un connecteur qui transmet déjà un UUID taxId explicite, une erreur de prix ou un calcul de taxe au checkout. Pour un tel dossier, reproduisez d’abord la préparation réellement utilisée : une ressemblance du message support ne prouve pas que les mêmes mécanismes sont en cause.
Paradoxalement, l’apparition d’une seconde taxe peut rendre visible une distinction que le flux réduisait jusque-là à un taux. Le refus de résolution est alors une protection utile. L’objectif opérationnel n’est pas de rendre chaque ligne importable à tout prix, mais de rendre chaque affectation explicable. Le responsable référentiel décide de la correspondance, tandis que le middleware conserve le lien entre décision, produit et version du mapping.
Le contrat Sync distingue un taux recherché d’un UUID choisi
Lire le résolveur disponible dans la version déployée
La documentation officielle des lots Sync décrit l’interface REST POST /api/_action/sync et les opérations upsert ou delete. Elle présente aussi des objets de résolution contenant resolver et value. Pour tax.tax_rate, la correspondance n’est retenue que lorsqu’une seule fiche possède le taux demandé. Vérifiez cette capacité sur votre release avant de remplacer un format UUID déjà utilisé par un objet de résolution.
Le code publié du résolveur dans Shopware 6.7.15.1 regroupe les lignes par tax_rate et impose HAVING COUNT(id) = 1. La sélection SQL contient MIN(id), mais cette expression ne sert pas à départager plusieurs taxes : le groupe contenant plusieurs identifiants est écarté par la condition. Le seuil d’acceptation de cette recherche est exactement une correspondance, et non au moins une fiche portant le taux. Copier seulement MIN(id) dans un diagnostic conduirait donc à expliquer l’inverse du comportement réel.
Distinguer référence non résolue et écriture acceptée
La documentation associe une référence non résolue à FRAMEWORK__API_INVALID_SYNC_RESOLVERS lorsque le repli autorisé n’est pas demandé. Notre programme appelle directement le résolveur de taxe : il observe une propriété resolved égale à null. Il ne traverse ni le contrôleur HTTP ni l’écriture DAL, et ne produit donc aucun statut HTTP de Shopware. Le résultat local et l’erreur contractuelle documentée constituent deux preuves différentes.
L’option nullOnMissing concerne le traitement effectué autour des résolveurs ; elle ne choisit pas la bonne taxe. Dans la définition publiée du produit, taxId porte notamment les indicateurs Required et Inherited. Une valeur nulle ne peut pas être présentée comme une réparation universelle : la validité dépend aussi du contexte du produit et de l’héritage. Il faut qualifier l’écriture réelle avant de conseiller ce repli.
Atelier : exécuter le résolveur natif sur des taxes fictives
Reproduire la différence entre une et deux correspondances
Le programme PHP complet à télécharger charge trois fichiers originaux de la release, vérifiés par empreinte : AbstractFkResolver, FkReference et TaxRateFkResolver. Il utilise une véritable connexion Doctrine DBAL 4.4.5, sans doublure de Connection. Chaque scénario crée sa table tax dans une base SQLite éphémère. Les identifiants composés de lettres « a », « b » ou « c » ainsi que les taux utilisés sont des données fictives, sans signification fiscale attribuée.
Dans le premier cas, la seule taxe au taux 20 possède l’identifiant A. Dans le second, A et B partagent cette valeur. Le programme demande la même résolution, mais le résultat passe de l’UUID de A à null. L’inversion de l’ordre d’insertion produit également null. Cette comparaison démontre le traitement du doublon dans la fixture, sans chercher à reproduire une sélection du premier élément côté middleware.
{
"unique_rate": ["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"],
"duplicate_rate": [null],
"reverse_insertion": [null],
"missing_rate": [null]
}
Exécuter un témoin local avec ses dépendances qualifiées
La sortie ci-dessus extrait les observations réelles des quatre scénarios nommés ; elle n’est pas une réponse de l’API. Le programme a été exécuté sous PHP 8.5.11 avec SQLite 3.51.2, dans un espace réseau isolé et avec la racine en lecture seule. Les bases restent en mémoire. Les 461 fichiers originaux des quatre paquets Composer concernés, dont 449 fichiers PHP, ont été comparés aux archives officielles ; les trois fichiers Shopware sont également inchangés.
Pour rejouer l’exercice, préparez séparément les dépendances locales et les trois sources de la release indiquée. Le programme vérifie leur version et leurs empreintes avant l’exécution. Le second argument désigne votre répertoire de sources, pas une boutique distante. Aucun jeton, compte vendeur, client réel ou accès d’administration Shopware n’est demandé. Téléchargez le fichier source puis exécutez-le avec PHP dans cet environnement local, en conservant les contrôles de version inclus.
composer require doctrine/dbal:4.4.5 --no-plugins --no-scripts
php shopware_tax_rate_resolution.php.txt \
/local/vendor/autoload.php /local/released-sources
# Résultat observé :
# checksPassed: 71
# cases: 15
# nativeResolverCalls: 16
# shopwareApiCalls: 0
# realProductsChanged: 0
| Référentiel fictif | Observation native |
|---|---|
| Une taxe au taux 20 | UUID de A résolu. |
| Deux taxes au taux 20 | Référence laissée à null. |
| Aucune taxe au taux 20 | Référence laissée à null. |
| Doublon sur un autre taux | Le taux unique demandé reste résolu. |
| nullOnMissing à true | Pas de choix effectué entre les taxes. |
| Nouveau doublon au second essai | Nouvelle référence non résolue. |
Ce que les quinze scénarios permettent réellement de décider
Séparer le taux absent du taux ambigu
Le même résultat null apparaît pour une recherche sans correspondance et pour une recherche avec plusieurs correspondances. Le champ resolved ne suffit donc pas à expliquer la cause au support. La recette doit conserver les candidats observés dans le référentiel de test : aucun, un seul ou plusieurs. En exploitation, une investigation autorisée doit retrouver cette information sans transformer automatiquement un échec de résolution en création d’une nouvelle taxe.
Le cas mixte contient une taxe unique au taux 20 et deux taxes au taux 10. Le résolveur renvoie l’UUID pour la première référence et null pour la seconde. Cela prouve une différence entre les objets résolus dans l’appel local. Cela ne prouve pas que le premier produit d’un lot HTTP a été enregistré pendant que le second échouait. Les transactions et le résultat d’écriture du lot doivent être testés séparément sur la version réellement exploitée.
Refaire la résolution lorsque le référentiel change
Un scénario résout d’abord A, ajoute ensuite B au même taux dans la base fictive, puis relance le résolveur avec une nouvelle FkReference. Le second résultat est null, tandis que l’ancien objet conserve son observation précédente. Ce détail compte dans un banc de test ou une adaptation interne : réutiliser un objet déjà résolu pourrait donner une impression de réussite qui ne représente plus la recherche courante.
Les autres cas couvrent notamment une chaîne numérique « 20.0 », deux références fraîches vers le même taux, une liste vide et une fixture au taux zéro. Ils vérifient les résultats obtenus dans cet environnement précis. Ils ne qualifient pas les décimales de tous les pilotes SQL, les règles fiscales d’un pays ou les extensions installées dans votre boutique. La compatibilité du schéma et des interfaces reste une vérification propre à votre installation.
Erreurs fréquentes qui débloquent le lot sans régler l’identité
Supprimer une taxe ou choisir le premier UUID
Deux taxes au même taux ne sont pas automatiquement des doublons métier à supprimer. Elles peuvent avoir été créées pour des usages que le taux ne décrit pas. Le connecteur ne doit pas effacer cette distinction pour satisfaire une recherche numérique. Faites qualifier les fiches par le responsable du référentiel et les équipes compétentes, puis décidez si elles doivent être conservées, rapprochées ou traitées par un mapping explicite.
Choisir arbitrairement le premier UUID crée une autre erreur : le lot passe, mais l’affectation dépend d’un ordre qui ne porte aucune décision métier. Le contre-test utile donne le même taux à A et B, inverse leur ordre et conserve l’UUID attendu dans le dossier ERP. Un mapping acceptable reste lié à cette identité convenue ; il ne change pas parce qu’une liste est triée différemment. Aucun taux commun ne constitue à lui seul cette preuve.
Confondre relance technique et correction du référentiel
Un retry à l’identique ne rend pas unique un taux ambigu. L’idempotence évite de multiplier certains effets, mais elle ne fournit pas l’identité manquante. Classez donc ce motif dans les décisions qui attendent une correction qualifiée, avec le code ERP, le taux, le produit et les candidats relevés. La journalisation doit permettre de retrouver cette ligne sans recopier inutilement tout le catalogue ou les données commerciales dans chaque trace.
La reprise ne doit pas non plus devenir une réimportation générale par réflexe. Un lot peut contenir des prix, des stocks et d’autres références dont l’état a changé entre deux tentatives. Avant un rejeu, relisez ce qui a réellement été enregistré et les garanties du chemin utilisé. Le témoin de résolveur ne remplace pas cette vérification des effets ; il permet seulement de retirer une ambiguïté précise de la préparation suivante.
Un timeout après un véritable envoi constitue encore un autre dossier : l’absence de réponse ne démontre ni le rejet ni l’acceptation du produit. L’observabilité doit séparer cet état incertain de l’ambiguïté détectée avant l’écriture. Recherchez alors les traces de la tentative et l’état distant avant toute décision de rejeu. Le coût caché apparaît lorsque le support doit reconstruire ces catégories depuis des messages tous réduits à « import en erreur ».
Plan d’action : attribuer la taxe puis reprendre les lignes concernées
Choisir entre recherche par taux et mapping d’identifiants
Commencez par relever la version Shopware, le format taxId préparé et les références de l’import refusé. Comparez les taxes candidates au code fiscal source, avec le responsable ERP et celui du catalogue. Si le taux désigne sans ambiguïté la bonne fiche dans le périmètre retenu, le résolveur peut rester une option. Si plusieurs fiches doivent coexister, une correspondance approuvée vers un UUID devient un choix à qualifier plutôt qu’un algorithme de départage improvisé.
Cette correspondance doit être rattachée à la bonne boutique et à l’environnement concerné. Un UUID relevé dans une fixture ou une autre installation n’est pas une identité portable garantie. Conservez le code source, l’UUID cible, la justification et la version du mapping dans une configuration révisable. L’intégrateur ERP fournit la signification métier ; l’équipe de connexion vérifie sa traduction et les droits techniques nécessaires à sa lecture et à son utilisation.
Exercer la reprise et le retour à la configuration précédente
Préparez une recette représentative : taux unique, absent, ambigu, plusieurs produits affectés et changement du référentiel entre deux tentatives. L’acceptation exige la taxe attendue pour chaque produit retenu, ainsi que le maintien en revue des lignes non décidées. Le monitoring peut séparer ces motifs et leur ancienneté ; fixez vos seuils d’alerte selon l’exploitation, sans les confondre avec des limites imposées par Shopware. Le runbook explique qui peut approuver la correspondance et lancer la reprise ciblée.
Lors du passage en service, conservez la version précédente du mapping et le périmètre des lignes traitées. Le rollback d’une configuration arrête les préparations suivantes ; il n’annule pas à lui seul des écritures déjà acceptées. Relevez ces écritures avant de décider une correction distante. L’ouverture du flux suit les preuves de cette recette, avec une file de revue identifiable pour les taxes dont la correspondance reste indécidable.
- Références ERP et Shopware rapprochées avec leur environnement explicitement conservé.
- Ambiguïtés distinguées des absences avant toute nouvelle tentative de synchronisation.
- Produits relus après la reprise pour comparer la taxe attendue à l’état observé.
- Décisions restantes confiées à un responsable qui peut expliquer chaque correspondance.
Deux diagnostics voisins pour qualifier la donnée source
Un libellé lisible ne constitue pas une clé métier stable
Le diagnostic consacré à une option Pipedrive renommée face au code ERP traite une autre forme de perte d’identité : le libellé présenté à l’utilisateur ne doit pas devenir automatiquement le code de gestion. Ici, c’est le taux numérique qui ne suffit plus à désigner une taxe. Les deux situations appellent une correspondance expliquée, sans partager pour autant le contrat technique du fournisseur.
La différence opérationnelle mérite de rester visible dans le dossier de recette. Une option renommée peut conserver son identifiant alors que son affichage change ; deux taxes peuvent conserver le même taux tout en possédant deux identifiants distincts. Dans Shopware, la priorité est donc de connaître la fiche attendue et le nombre de candidates. Une comparaison de libellés ou de valeurs numériques ne remplace pas ce rapprochement des identités.
Un prix exporté doit conserver son contexte propre
Le cas PrestaShop et prix contextualisé en multiboutique aide à distinguer un montant isolé de la configuration qui l’explique. Il complète le diagnostic des données commerciales, sans fournir une règle de calcul Shopware. Une affectation de taxe résolue et un prix ERP correctement interprété restent deux contrôles séparés dans une recette e-commerce.
Pour un produit bloqué, séparez la fiche de correspondance de taxe du dossier de prix : valeur source, configuration commerciale et montant préparé doivent pouvoir être relus indépendamment. Corriger taxId ne suffit pas à approuver le prix ; inversement, obtenir le montant attendu ne démontre pas que la taxe choisie est celle convenue avec l’ERP. Cette séparation réduit les corrections croisées dont le support ne peut plus expliquer l’origine.
Conclusion : affecter une identité plutôt que forcer un taux
Un taux présent n’est pas nécessairement une taxe identifiable. Le résolveur publié pour Shopware 6.7.15.1 laisse volontairement la référence non résolue lorsque plusieurs fiches partagent ce taux. Les quinze scénarios exécutés permettent de reconnaître cette situation, de la distinguer d’une recherche absente et de vérifier qu’un ordre d’insertion différent n’apporte aucune décision métier supplémentaire.
Le premier livrable utile est une correspondance comprise entre code fiscal source et taxe cible, ou une décision explicite de maintenir la ligne en revue. Ce choix précède la reprise des produits concernés. Il ne requiert ni suppression précipitée du référentiel ni promesse qu’une option nullOnMissing rendra toutes les écritures acceptables.
Notre accompagnement pour intégrer Shopware au SI peut qualifier les interfaces, le schéma attendu, les correspondances ERP et les scénarios de reprise avec vos équipes. Le contrôle final porte sur la taxe réellement observée sur le produit après l’écriture autorisée, et sur les lignes que le connecteur a correctement laissées en attente d’une décision.
Pour structurer ce flux, notre accompagnement en intégration API peut cadrer le contrat entre donnée source, résolution et effet enregistré. Le travail commence par les références de taxe et les produits bloqués, puis associe les responsables du référentiel à une recette reproductible. Le périmètre s’élargit lorsque l’équipe peut expliquer les affectations constatées et reprendre les lignes décidées avec la version de mapping approuvée.