Le chargement du catalogue SAP s’est terminé avec un HTTP 200, mais la référence attendue n’existe pas. Ce symptôme peut venir du bilan du connecteur, qui ne lit que le statut du lot. Dans le corps de la réponse, une écriture a été refusée et son groupe transactionnel a été annulé. Relancer tout le fichier peut alors reproduire les opérations déjà réussies dans un autre groupe.
En pratique, le statut du batch et le résultat d’un changeset ne décrivent pas la même chose. L’un qualifie l’enveloppe d’échange ; l’autre concerne un ensemble d’écritures qui doivent réussir ensemble. La décision de reprise commence par retrouver ces frontières, les réponses reçues et les opérations qui ne disposent encore d’aucun résultat vérifié.
Le scénario suivi ici est fictif : un lot contient une lecture, un groupe « catalogue » avec création puis mise à jour d’un produit, et un groupe indépendant « suivant ». Le laboratoire lit des réponses multipart fabriquées localement. Il ne crée aucune fiche produit SAP et ne simule pas le moteur transactionnel de l’ERP ; il vérifie comment le connecteur interprète les preuves disponibles.
Notre accompagnement en intégration API inclut cette qualification des résultats et des reprises. Pour des échanges SAP avec vos applications métier, Dawap travaille avec votre installateur ERP sur la version, le contrat du Service Layer et les objets réellement concernés.
Pour qui : un lot SAP accepté masque une écriture refusée
Distinguer l’import incomplet du simple défaut d’affichage
Le diagnostic intéresse les équipes qui envoient plusieurs opérations au Service Layer et ramènent un résultat unique au logiciel appelant. Un écran « import terminé » peut alors cacher plusieurs situations : groupe réussi, groupe refusé, lecture réussie ou résultat manquant. L’équipe catalogue ne peut pas choisir une reprise fiable avec une seule couleur pour ces quatre états.
Commencer avec une référence et un lot identifiables, puis relire l’objet attendu dans le contexte autorisé. Si le produit existe avec les bonnes propriétés mais reste absent d’un écran ou d’un export secondaire, il faut suivre ce parcours distinct. Une anomalie de visibilité ne démontre pas que le changeset a échoué.
Garder le périmètre synchrone multipart explicite
Le laboratoire vise une réponse synchrone OData V4 de type multipart, sur un plan de requêtes connu. Il ne traite pas les lots JSON, les échanges asynchrones, les réponses intermédiaires ni toutes les variantes possibles d’un client OData. Toute forme différente est refusée ou laissée à une qualification adaptée, au lieu d’être interprétée comme un succès.
La référence SAP actuelle présente OData V4 comme protocole principal depuis FP2405, tout en conservant V3 pour compatibilité. Le chemin /b1s/v2 correspond à OData V4 : le chiffre du chemin ne désigne pas OData V2. Vérifier le protocole et la version installée avant d’appliquer un exemple à un client existant.
Lire l’enveloppe HTTP puis chaque unité du lot
Le 200 du batch ne termine pas le contrôle
La documentation SAP distingue le retour de l’enveloppe et les sous-réponses : un format de lot valide peut produire un retour positif même lorsqu’une opération échoue. L’exploitation doit donc attendre et analyser le corps complet, puis conserver le résultat des unités envoyées. Recevoir les en-têtes HTTP n’autorise pas encore à annoncer que les écritures sont terminées.
Le middleware devrait garder une correspondance entre la demande métier, son plan de lot et les unités reçues. Dans notre exemple, les noms « lecture », « catalogue » et « suivant » sont des repères locaux du connecteur. Ils ne sont pas des propriétés SAP ajoutées automatiquement à la réponse. Le plan conservé explique leur association aux parties du lot.
Une réponse multipart se lit comme une structure
Le standard OData décrit une enveloppe MIME composée de parties, certaines contenant à leur tour les réponses d’un changeset. Un découpage improvisé du texte sur le mot HTTP ou sur une chaîne supposée fixe perd cette hiérarchie. Le laboratoire utilise le parseur MIME de la bibliothèque standard Python pour conserver les groupes avant de lire les statuts internes.
Cette démarche ne transforme pas le programme en client HTTP complet. Il reçoit un type de contenu et des octets synthétiques déjà disponibles en mémoire. Les délais, la compression, les certificats, la taille maximale des réponses et les en-têtes de transport restent à traiter dans le véritable client. L’exercice isole la lecture des unités, pas toute la connexion à SAP.
Appliquer l’annulation au changeset concerné
Une seule erreur peut représenter plusieurs écritures annulées
Un changeset constitue une unité atomique : ses opérations s’appliquent ensemble ou aucune ne s’applique. En cas d’échec, la réponse peut contenir une seule partie d’erreur pour tout le groupe, plutôt qu’une réponse par opération. Un compteur qui attend deux résultats positifs ou négatifs séparés peut alors produire un bilan trompeur.
Pour notre groupe « catalogue », les opérations 1 et 2 forment une même décision. Lorsque le résultat qualifié du groupe est un échec, le connecteur ne doit pas présenter la première comme conservée uniquement parce qu’elle précédait l’opération fautive. Le laboratoire classe le groupe entier ; il ne prétend pas observer les transactions internes d’un serveur SAP.
Le groupe précédent ne disparaît pas avec le suivant
Exemple concret fictif : le groupe « catalogue » possède ses réponses finales attendues, puis le groupe « suivant » renvoie une erreur. La preuve du premier groupe reste distincte de l’échec du second. L’atomicité du changeset ne signifie pas que toutes les unités indépendantes du batch partagent une transaction unique.
Choisir la frontière transactionnelle fait donc partie du contrat métier. Coupler création et enrichissement d’un même article peut être nécessaire ; réunir arbitrairement tout un catalogue augmente le nombre de références affectées par une seule donnée refusée. Le bon découpage se décide à partir des dépendances, avec l’équipe ERP, puis se vérifie sur la version cible.
Rapprocher les opérations avec Content-ID
Ne pas utiliser la position interne comme identifiant
OData V4 permet de renvoyer les réponses d’un changeset dans un ordre différent et fournit Content-ID pour les rapprocher des requêtes. Cette identité appartient à la partie MIME. Dans l’exercice, par exemple, une réponse 204 portant l’identifiant 2 peut précéder la réponse 201 portant l’identifiant 1 sans changer le résultat attendu du groupe.
Le plan local conserve donc les identifiants et les statuts finaux attendus. Une réponse manquante, un identifiant inconnu ou un doublon empêche la validation. Le code ne réaffecte pas silencieusement la première réponse disponible à la première opération du plan ; cette facilité transformerait un défaut de corrélation en confirmation artificielle.
Séparer référence temporaire et protection contre les doublons
La documentation SAP montre aussi l’usage d’un Content-ID pour référencer l’URI d’une création dans le même changeset. Cette fonction ne donne pas une clé d’idempotence persistante pour les reprises de lots. Elle ne remplace pas la recherche d’une référence déjà créée lors d’une tentative précédente dont le résultat serait inconnu.
Éviter également de transformer cette référence d’URI en mécanisme universel de substitution dans n’importe quel champ JSON. Les possibilités dépendent du contrat effectivement supporté. Le lecteur de réponses joint ne construit aucune requête de ce type et ne confirme aucune capacité de référence dans les corps de requête d’une installation cliente.
Laboratoire : interpréter des réponses multipart sans contacter SAP
Exécuter les 44 contrôles locaux
Le fichier batch_response_inventory.py utilise Python 3.9 ou plus récent et sa bibliothèque standard. Il fabrique des parties application/http, des groupes multipart et des enveloppes complètes. Aucun fichier client, cookie, secret de connexion ou accès réseau n’est demandé.
Le plan fictif contient une lecture attendue à 200, un changeset avec les identifiants 1 et 2 attendus à 201 et 204, puis un second changeset attendu à 201 pour l’identifiant 3. Ces statuts constituent le contrat réduit du laboratoire. D’autres opérations ou modes de réponse nécessitent une qualification propre, pas un élargissement automatique à tous les codes 2xx.
python3 batch_response_inventory.py
# 44 local checks passed. Native SAP transactions: 0;
# HTTP calls: 0; ERP writes: 0.
Comprendre ce que le parseur refuse
Les contrôles incluent une fin de MIME tronquée, un type de contenu incorrect, un Content-ID absent et une réponse intermédiaire 202. Le modèle refuse aussi une partie ultérieure après un échec, car sa politique locale suppose l’arrêt sur erreur. Il ne déduit pas que l’option continue-on-error est disponible ou activée dans SAP.
Un HTTP 400 contenant un simple message de refus d’intermédiaire n’est pas assimilé automatiquement à l’échec transactionnel SAP. Le laboratoire attend une erreur structurée avant de classer un changeset comme refusé. Cette forme ne prouve pas à elle seule l’origine authentique d’une réponse ; cette origine relève du client, du chemin réseau et des traces autorisées de l’installation réelle.
Transformer les résultats du laboratoire en décisions
Les états ci-dessous décrivent ce que notre lecteur local a pu qualifier dans ses fixtures. Ils ne constituent pas un journal de transactions réelles. La différence entre absence de preuve et échec qualifié doit rester visible jusque dans l’écran de reprise du connecteur.
| Observation | État local | Décision |
|---|---|---|
| Lecture attendue à 200 | Lecture réussie | Conserver son résultat |
| Groupe avec tous ses identifiants et statuts attendus | Succès du groupe | Rapprocher les objets métier |
| Erreur qualifiée du changeset | Échec du groupe | Corriger la cause avant reprise |
| Unité sans partie reçue | Non rapportée | Ne pas certifier son résultat |
| Structure ou identité ambiguë | Réponse refusée | Conserver le dossier ouvert |
Distinguer l’arrêt attendu d’un résultat simplement absent
La documentation SAP décrit l’arrêt du batch à la rencontre d’une erreur. Dans un parcours conforme à ce comportement, les unités suivantes n’ont pas été traitées. Le lecteur local conserve pourtant l’état prudent « non rapporté » pour une unité sans réponse : il n’a pas vérifié la configuration réelle ni toute la chaîne de transport du client.
Ce choix évite de convertir une enveloppe incomplète, une transformation d’intermédiaire ou un contrat différent en certitude d’absence d’effet. Une clôture métier exige de rapprocher les unités du plan, le comportement natif qualifié et les objets effectivement retrouvés. La règle de reprise doit dire quand cette recherche complémentaire devient obligatoire.
Le succès de protocole ne valide pas le catalogue
Le programme ne vérifie pas les SKU, les taxes, les unités de vente ou les propriétés des articles obtenus. Il rapproche des statuts et des identifiants d’opérations dans un plan fictif. Une demande contenant le mauvais code article peut être acceptée tout en répondant mal au besoin du métier. Cette vérification reste à faire sur les documents et références visés.
Un seuil de sortie utile combine donc des unités techniques expliquées et un rapprochement métier sans anomalie bloquante sur la cohorte de recette. Le nombre de sous-réponses reçues ne suffit pas. Le responsable catalogue doit pouvoir retrouver les références créées ou modifiées et distinguer celles qui demandent encore une intervention.
Préparer la reprise à partir des effets connus
Corriger le groupe refusé avant un nouvel envoi
Une erreur métier expliquée appelle une correction de sa cause : donnée, dépendance ou règle native. Le connecteur conserve la version du payload et la composition du changeset refusé. Recréer un lot à partir du catalogue courant sans retrouver cette demande peut modifier le périmètre de la reprise et faire disparaître l’explication initiale.
Le groupe à rejouer doit être revalidé selon l’état présent de SAP. Entre-temps, un opérateur ou un autre flux peut avoir créé ou modifié la référence. Le rollback natif de la tentative refusée ne signifie pas que le monde est resté inchangé jusqu’à la reprise. Le choix création, mise à jour ou suspension doit être explicite et traçable.
Traiter une perte de réponse comme une issue inconnue
Un timeout après envoi n’établit pas qu’un changeset a échoué. Le contrat de reprise relie l’entrée au plan conservé et attribue la recherche des effets avant le retry d’une création. Le runbook doit retrouver la société, les références demandées et les lectures autorisées. Le Content-ID de la tentative ne constitue pas un identifiant durable du produit créé ; la corrélation métier et les résultats conservés doivent permettre ce rapprochement.
Le coût caché d’un rejeu global apparaît lorsque l’équipe traite ensuite des doublons ou écrase une correction manuelle. Une stratégie de backoff peut limiter la pression lors d’une indisponibilité transitoire, mais elle ne résout pas l’issue inconnue d’une écriture. La politique d’idempotence doit être conçue pour le contrat cible, avec un responsable des exceptions.
Instrumenter le connecteur sans mélanger SAP et le système destinataire
Conserver le contexte avec le plan et la réponse
Le journal de reprise relie installation, société, demande métier, version de mapping, unités du batch et réponse source autorisée. Les responsabilités distinguent la lecture du protocole, le diagnostic de la donnée refusée et l’autorisation de reprise. Le runbook précise le seuil qui arrête un lot et les preuves requises pour le rouvrir.
Le monitoring doit suivre séparément les refus de changeset, les réponses non interprétables et les unités sans résultat qualifié. Un premier signal faible est l’écart entre la couleur « succès » du transport et le nombre de références métier rapprochées. Un second est la hausse des reprises manuelles après une évolution du SDK, alors que la latence réseau reste stable.
Ne pas attribuer une transaction distribuée au batch
Un changeset SAP ne garantit pas l’annulation d’un email déjà envoyé, d’une préparation WMS engagée ou d’un autre appel API. Si le workflow traverse plusieurs logiciels, il faut définir l’enchaînement et le traitement d’un effet déjà produit. Le périmètre atomique du Service Layer doit rester distinct du périmètre complet du processus métier.
Paradoxalement, un lot plus petit peut rendre la reprise plus fiable si ses dépendances sont explicites et son résultat rapprochable. À l’inverse, séparer deux opérations qui doivent réussir ensemble peut laisser un objet inutilisable. L’arbitrage concerne le sens du processus ; le nombre de requêtes HTTP économisées vient après cette décision.
Plan d’action : rendre chaque unité du lot explicable
- Reconstituer une demande de recette. Le responsable catalogue choisit une référence synthétique et décrit l’état attendu. L’intégrateur retrouve le protocole, la version du Service Layer et le plan exact des unités envoyées. L’installateur SAP confirme les dépendances et les règles susceptibles de refuser l’écriture. Cette étape doit distinguer opérations indépendantes et opérations qui doivent réussir ensemble. Différer l’augmentation des volumes tant que l’équipe ne peut pas relier un résultat du lot à une intention métier précise.
- Comparer la structure reçue au plan conservé. Le développeur vérifie le type multipart, la fin complète du message et les identifiants des réponses du changeset. L’exploitant conserve les traces autorisées et l’origine de la réponse, sans exposer les cookies. Une ambiguïté maintient le dossier ouvert ; elle ne devient pas une réussite par défaut. La recette inclut un groupe réussi, un groupe refusé et une unité sans réponse afin de tester les trois décisions de traitement réellement nécessaires.
- Définir la correction et la reprise autorisées. Le référent ERP explique la cause native du refus et valide la donnée corrigée. L’intégrateur prépare uniquement le périmètre dont l’issue est connue ou a été rapprochée. Le runbook distingue refus explicite et perte de réponse. Le retour arrière du connecteur conserve les preuves de la tentative précédente, car il ne supprime pas les effets déjà produits dans SAP. Refuser un rejeu global qui mélangerait des unités réussies et des écritures encore indéterminées.
- Contrôler le catalogue après la reprise. Le métier retrouve les références attendues et les propriétés qui motivent l’import. L’exploitation rapproche ces objets avec les unités techniques, puis classe les exceptions restantes par cause et responsabilité. Le seuil de clôture exige des résultats expliqués sur la cohorte convenue, une trace de la version corrigée et une procédure praticable pour le prochain incident. Une réponse HTTP positive ne doit jamais remplacer cette lecture commune du résultat par les équipes concernées.
Erreurs fréquentes dans la lecture et le rejeu d’un batch
Compter les erreurs comme s’il y en avait une par opération
Si le changeset attendu contient deux écritures et revient avec une seule erreur de groupe, le bilan ne doit pas annoncer « une écriture refusée, une écriture réussie ». La forme de réponse a changé avec le résultat atomique. Le middleware doit conserver la composition du groupe pour expliquer quelles opérations sont concernées par ce refus.
L’autre raccourci consiste à remplir les réponses absentes avec un succès, parce que l’enveloppe est complète. Une fin MIME valide ne prouve pas que toutes les unités métier ont un résultat positif. Le laboratoire maintient les unités manquantes à l’état non rapporté et exige une décision explicite pour poursuivre leur traitement.
Confondre redémarrage technique et annulation des effets
Relancer un worker, purger sa queue ou revenir à une ancienne version du connecteur ne retire pas une référence déjà créée par un groupe réussi. La preuve doit survivre à ce redémarrage. Une opération de compensation éventuelle relève d’une décision métier et d’un contrat distinct ; le lecteur de réponses joint n’en propose aucune.
Ne pas supposer non plus qu’une option standard OData est activée dans SAP simplement parce qu’elle existe dans la norme. L’arrêt sur erreur et toute possibilité de poursuite doivent être confirmés sur l’interface utilisée. Un nouveau comportement du SDK mérite une recette de ses résultats avant l’élargissement du batch en production.
Sources et guides complémentaires pour la recette SAP
Rapprocher le protocole standard et l’implémentation SAP
La section Batch Operations de Working with SAP Business One Service Layer décrit le comportement natif. Le standard OData V4, section 11.7 précise la structure et la corrélation des réponses. Les deux périmètres doivent être distingués.
La référence Service Layer qualifie les versions de protocole ; le document OData Client for Service Layer illustre des échanges multipart du client. Ces références ont été consultées le 15 octobre 2026. Les fixtures jointes restent entièrement synthétiques.
Relier le refus à sa cause sans rouvrir tout le SI
Si une propriété personnalisée se perd avant l’écriture, le diagnostic SAP Business One et champ UDF absent du connecteur suit la réponse, le SDK et le mapping. Si le lot utilise le mauvais contexte, la lecture sur les sessions SAP séparées par société traite cette autre frontière. Un statut d’erreur ne suffit pas à choisir entre ces deux causes.
Les 44 contrôles ne certifient aucune installation SAP, aucune atomicité réelle ni aucune qualité des articles du catalogue. Ils montrent une interprétation locale de structures connues, avec refus des formes non prévues. La recette de votre flux doit encore vérifier les demandes autorisées, les réponses natives, les effets métier et les reprises dans un environnement adapté.
Conclusion : reprendre le bon groupe avec une issue expliquée
Le connecteur doit conserver trois lectures distinctes : l’enveloppe HTTP, le résultat de chaque unité du lot et l’état métier des références concernées. Un 200 global ne ferme aucune de ces vérifications à lui seul. La réponse d’un changeset doit être rapprochée du groupe demandé, même lorsqu’une seule erreur représente plusieurs écritures annulées.
Notre priorité serait de qualifier la réponse complète et son contexte avant de choisir une reprise. Les groupes réussis, les groupes refusés et les unités sans résultat restent séparés. Cette distinction évite qu’un incident sur une référence provoque le rejeu indiscriminé du catalogue ou l’effacement des preuves des opérations précédentes.
La recette doit également vérifier les identifiants métier et les propriétés obtenues. Une corrélation Content-ID correcte ne confirme pas le sens d’une demande mal préparée. Le résultat attendu est un catalogue expliqué et rapproché, avec des exceptions attribuées à une cause et à une équipe capable de les résoudre.
Dawap vous accompagne pour cadrer cette intégration API autour des lots SAP Business One, revoir les frontières transactionnelles et préparer les preuves de reprise avec votre installateur ERP. L’intervention relie le contrat du Service Layer aux décisions du catalogue, avec une procédure vérifiable pour les équipes qui doivent relancer le flux.