Implémentations Pipedrive — Dawap — 6 novembre 2026

Python 3.11 ou supérieur. Bibliothèque standard uniquement, sans installation.
Depuis ce dossier :
    python3 demo.py
    python3 -m unittest discover -s . -v

integration.py : client HTTP Pipedrive, journal SQLite, formulaire, collecte de
deals gagnés, lignes produits, passage vers un ERP simulé et qualification B2B.
test_integration.py : cas métier et serveur HTTP éphémère sur 127.0.0.1.
demo.py : cinq démonstrations déterministes, aucun accès distant.

Ce qui est réellement testé
- Répétition après réouverture de SQLite, concurrence entre deux connexions,
  réponse perdue, identité conflictuelle et absence de retry POST automatique.
- Pages API, curseur répété, limite de pages, 429 et atomicité inbox/checkpoint.
- Arrondi décimal, TVA exclusive, remise en pourcentage, lignes distinctes,
  total accepté et refus des règles commerciales non prises en charge.
- Commande locale unique malgré une réponse perdue, retour CRM et conservation
  de la version acceptée. Routage portail commercial/ADV et owner conservé.
- Sérialisation HTTP réelle, encodage des paramètres, token en en-tête,
  rejet des redirections et limite locale de requêtes.

Ce qui n'est pas attesté
Aucun appel vers Pipedrive, aucune sandbox distante, aucun ERP client, aucun
gain métier client mesuré. FakeApi et DemoErp sont explicitement des simulateurs.
Les contrats d'API ont été vérifiés dans les références officielles le 6/11/2026.
Les tests du transport HTTP local ne valident pas les permissions d'un vrai compte.

Périmètre et préparation d'une intégration réelle
1. Une base SQLite PAR connexion/entreprise Pipedrive ; fichier privé, hors webroot,
   sauvegardé et protégé. PostgreSQL avec contraintes équivalentes peut la remplacer.
2. Le formulaire s'adresse ici à un compte B2B déjà rapproché. Ses références
   account/contact sont résolues côté serveur depuis une identité autorisée.
   Ne jamais faire confiance aux owner_id/org_id/person_id d'un formulaire public.
   Importer les correspondances existantes, qualifier les comptes inconnus et
   autoriser explicitement une nouvelle identité avant de créer une personne.
   Ce programme ne dédoublonne pas tous les contacts historiques du CRM.
3. Valider le formulaire, authentifier les émetteurs internes, poser les protections
   anti-abus, consentements et durées de conservation adaptés au parcours.
4. Configurer un owner actif, les vrais pipeline/stage et type d'activité ; choisir
   l'activité native OU l'activité par API. Une règle native parallèle doublerait l'action.
5. La création du lead utilise POST /api/v1/leads ; persons/activities/deals et
   produits utilisent les opérations v2 documentées. Ne pas renommer v1 en v2.
6. Le client Pipedrive accepte un token personnel via son constructeur. Charger
   ce secret depuis l'environnement privé. Aucun token dans le code, le navigateur,
   la ligne de commande ou les journaux. OAuth/renouvellement non implémentés ici.
7. Un effet distant sans résultat confirmé reste bloqué. Store.resolve exige une
   vérification distante et une preuve conservée. Ne pas remettre automatiquement
   un effet pending à zéro après un délai : l'écriture peut avoir réussi.
   Un workflow ready peut reprendre ses étapes confirmées ; ses effets incertains
   restent bloqués. Un crash pendant le workflow exige aussi une reprise opérateur.
8. Le collecteur traite les deals gagnés visibles et modifiés dans [début,fin).
   Son checkpoint prouve leur stockage en inbox, PAS une commande ERP acceptée.
   Aucun snapshot isolation distant n'est supposé ; prévoir une fenêtre de
   recouvrement/réconciliation et une campagne séparée pour suppressions,
   archives, changements de droits et deals redevenus perdus. Tester les retards
   de visibilité. Les observations ne doivent pas devenir des commandes sans
   relecture et validation du document accepté.
   recover_orders consomme ensuite les IDs capturés seulement si un registre
   serveur fournit leur document accepté. Il rend accepted, needs_verification
   ou needs_accepted_document, sans effacer l'inbox ni créer à l'aveugle. Le
   laboratoire relie effectivement le deal 5071 à sa commande retrouvée après
   réponse perdue ; le deal 5072 reste sans commande faute de document accepté.
9. Le contrat produit de démonstration est EUR, arrondi HALF_UP par ligne,
   TVA exclusive, remise en pourcentage et vente ponctuelle. Variantes, devises
   différentes, remise globale, taxe inclusive et abonnements sont refusés.
   quote_from_api lit les remises globales et toutes les pages de produits.
   Le total accepté et la révision proviennent d'un document approuvé conservé
   hors du CRM. Cela ne constitue pas un service de signature électronique.
10. DemoErp n'est pas une API Sage, Odoo ou autre. L'adaptateur réel doit garantir
    une clé externe unique et une recherche fiable par cette clé. Sans ces
    capacités, une réponse perdue demande une décision manuelle ; pas de création
    automatique supplémentaire. Un deal produit une seule commande initiale dans
    cet exemple ; avenants, multi-commandes et annulations demandent un autre contrat.
11. Le retour ERP utilise une clé de champ texte Pipedrive de 40 caractères à lire
    dans DealFields. La clé aaaa... de demo.py est fictive. Ne pas la copier telle quelle.
12. reminder_decision ne fait que décider si une relance EN ATTENTE doit être
    annulée après lecture récente du statut payé. La limite de cinq minutes est
    un choix illustratif. Aucun e-mail ni paiement n'est envoyé par ces exemples.

Avant production : adapter les interfaces ERP, tester dans une sandbox Pipedrive
autorisée, vérifier droits et champs, superviser les files et formaliser le runbook.
Le plafond de requêtes du client n'est pas le calcul du budget journalier Pipedrive.

Sources
https://developers.pipedrive.com/docs/api/v1/Persons
https://developers.pipedrive.com/docs/api/v1/Leads
https://developers.pipedrive.com/docs/api/v1/Activities
https://developers.pipedrive.com/docs/api/v1/Deals
https://developers.pipedrive.com/docs/api/v1/DealProducts
https://pipedrive.readme.io/docs/guide-for-webhooks-v2
https://pipedrive.readme.io/docs/core-api-concepts-rate-limiting
https://support.pipedrive.com/en/article/troubleshooting-automations

Adaptateur PHP complémentaire du pilier SDK CRM
Opportunity.php, OpportunityReader.php, PipedriveOpportunityReader.php et
  check_reader.php requièrent PHP 8.2+ et Symfony
  HttpClient installé via Composer. Aucun SDK Pipedrive n'est nécessaire pour
  cet exemple de lecture. Depuis l'archive extraite :
    DAWAP_COMPOSER_AUTOLOAD=/chemin/prive/vendor/autoload.php php check_reader.php
  Sept contrôles utilisent MockHttpClient ; aucune requête distante.
