partiduo-superpdp
= partiduo-superpdp — plateforme agréée SUPER PDP :toc: left :toc-title: Table des matières :icons: font
Partiduo est le portage en Crystal de https://noalyss.eu[NOALYSS], logiciel libre de comptabilité créé et maintenu par Dany De Bontridder. Partiduo n'est pas un projet officiel NOALYSS.
Ce dépôt est l'extension SUPERPDP de Partiduo : l'adaptateur de la plateforme agréée https://www.superpdp.tech[SUPER PDP] pour l'extension EINV (partiduo-einvoicing, facturation électronique de la réforme française et Peppol belge). Il n'apporte qu'une implémentation d'Einvoicing::Connector, son paramétrage et ses écrans de raccordement (ADR-004 D8). L'extension amont de NOALYSS la plus proche, peppol-connect, parlait à un point d'accès qui n'est pas une plateforme agréée ; EINV la remplace, et SUPER PDP en est le premier adaptateur.
La spécification est dans ../partiduo-docs/ : ADR-004 (facturation électronique, D2 à D9, en particulier D8), ADR-003 (contrat d'extension), ADR-005 D4 (interface d'une extension), ADR-006 D3 et D5. Les décisions propres à ce dépôt sont consignées dans ../partiduo-app/DECISIONS.adoc (D-SPDP-001 à D-SPDP-014), puis dans link:DECISIONS.adoc[] (à partir de D-SPDP-015) ; les blocages dans ../partiduo-app/BLOCAGES.adoc (B-SPDP-). Référence du contrat : link:doc/api/superpdp.adoc[].
== Fonctions
[cols="1,3",options="header"] |=== |Fonction |Dans SUPERPDP
|API |API JSON SUPER PDP https://api.superpdp.tech/v1.beta/ (l'API AFNOR de SUPER PDP reste couverte par l'adaptateur XP Z12-013 d'EINV). Échanges par le transport d'EINV : TLS vérifié, plateforme simulée dans les specs.
|Authentification |OAuth 2.1, deux modes : client credentials (application SUPER PDP de la société, client_id et client_secret saisis puis essayés avant d'être enregistrés) et authorization code (application OAuth de l'opérateur de l'instance, redirection vers https://api.superpdp.tech/oauth2/authorize avec login_hint, superpdp_company_number et superpdp_company_number_scheme fr_siren ou be_numero_entreprise, retour sur la route de rappel de l'instance, state anti-CSRF à usage unique, PKCE S256). Jeton d'accès renouvelé automatiquement (expiration, refus 401) ; jeton de rafraîchissement renouvelé à chaque usage, stocké chiffré, sous verrou PostgreSQL ; révocation RFC 7009 à la déconnexion.
|Mode |Bac à sable ou production déduit des identifiants (GET /companies/me), affiché en permanence (écran SUPER PDP et bandeau des écrans d'EINV).
|Émission |POST /invoices du PDF/A-3 Factur-X de la Facturation (CII avec note BAR pour le B2C), external_id et processing_rule ; UBL PEPPOL BIS pour un client étranger (Belgique par Peppol, adresse 0208). Reprise idempotente d'un dépôt dont la réponse s'est perdue (recherche par external_id).
|Réception et statuts |GET /invoices?direction=in et GET /invoice_events avec starting_after_id, page après page jusqu'à has_after = false (curseur = dernier identifiant lu, ADR-004 D2) ; fichier original (format=original) déposé dans la boîte « Justificatifs à traiter ».
|Statuts émis |POST /invoice_events : Refusée (fr:210, motif et note), Encaissée (fr:212, ventilée par taux de TVA — règle BR-FR-CDV-14), autres statuts de l'acheteur ; jamais relus comme reçus ; reprise idempotente.
|Annuaire |Annuaire français (french_directory) : adresses SIREN, SIREN_SIRET, SIREN_SUFFIXE, SIREN_SIRET_CODEROUTAGE, schéma Peppol 0225 ; numéro d'entreprise belge en 0208 ; lignes d'annuaire de la société.
|E-reporting |B2B et B2C facturé : fait par SUPER PDP à partir des factures (note BAR) et de « Encaissée ». International : b2bint_invoices ; B2C sans facture : b2c_transactions, b2c_payments. Régime de TVA de l'entreprise (PATCH /companies) réglable à l'écran.
|Erreurs |Réponses http_ko (code HTTP, message) ; 429 et 503 rejoués après délai ; coupure réseau rejouée pour une lecture seulement ; 401 → jeton renouvelé puis « raccordez de nouveau » ; entreprise non vérifiée (KYB) signalée.
|Interface |ui/bulma/, montée sous /ext/SUPERPDP/ : raccordement (deux modes), état de la connexion (mode, entreprise, vérification, lignes d'annuaire, dernière synchronisation), régime de TVA, vérification, déconnexion. |===
== Dossiers belges
SUPER PDP envoie et reçoit les factures des entreprises belges par Peppol (documentation SUPER PDP, page « Belgique », https://www.superpdp.tech/documentation/12[], vérifiée le 25 octobre 2026). L'extension reste donc ouverte aux dossiers de régime be (ADR-004 D8). Conditions propres à la Belgique :
. Souscription de l'éditeur. Aloli souscrit l'offre Belgique par courriel à SUPER PDP (objet « Souscription Belgique superpdp_company_number_scheme be_numero_entreprise). Le mode client credentials ne sert pas aux dossiers belges. Ce mode n'a pas encore été essayé contre SUPER PDP : il faut d'abord déclarer l'application OAuth de l'opérateur (B-SPDP-004), voir « Raccorder une entreprise par délégation OAuth » ci-dessous. . Bac à sable. L'inscription dans l'annuaire Peppol de test n'est pas automatique : sur l'entreprise de test, « Nouvelle ligne d'annuaire… » avec le schéma belge 0208.
== Raccorder une entreprise par délégation OAuth
Préalable aux dossiers belges (ADR-004 D8, B-SPDP-004, D-SPDP-015). Le mode authorization code demande une application OAuth de l'opérateur, déclarée dans le compte SUPER PDP de l'opérateur : c'est un geste sur ce compte, que Partiduo ne fait pas. Ce guide le décrit, puis l'essai de bout en bout en bac à sable, enfin la production.
Pages de la documentation SUPER PDP suivies (lues le 26 octobre 2026) :
- « Authentification », https://www.superpdp.tech/documentation/4[] : authorization code (
https://api.superpdp.tech/oauth2/authorize,https://api.superpdp.tech/oauth2/token),client_idetclient_secret« à récupérer dans l'interface SUPER PDP », Redirect URL identique à celle renseignée dans l'interface SUPER PDP, aucun scope, champs pré-remplis (login_hint,superpdp_company_numberetsuperpdp_company_number_scheme:sandbox,fr_sirenoube_numero_entreprise), révocation RFC 7009, jeton d'accès de 30 minutes, jeton de rafraîchissement d'un an renouvelé à chaque usage ; - « Belgique », https://www.superpdp.tech/documentation/12[] : souscription, vérifications KYC et KYB, application OAuth liée à l'entreprise de production, bac à sable avec une entreprise et une application « bac à sable », ligne d'annuaire belge à ajouter à la main ;
- « Démarrage rapide », https://www.superpdp.tech/documentation/2[] : compte, entreprises fictives Burger Queen et Tricatel, « Applications » puis « Nouvelle application… », secret affiché une seule fois ;
- « Annuaire », https://www.superpdp.tech/documentation/7[] : adresse Peppol belge = schéma
0208et numéro d'entreprise (BCE) ; - exemple de SUPER PDP, https://github.com/superpdp/examples/blob/main/erp.go[] : serveur local avec la Redirect URL
http://localhost:8081/callback, une adresse locale enhttpest donc admise pour le bac à sable.
=== 1. Application OAuth de l'opérateur, en bac à sable
. Se connecter au compte SUPER PDP de l'opérateur (https://www.superpdp.tech[], « Connexion »). Le compte contient les entreprises bac à sable Burger Queen et Tricatel. . « Applications », puis « Nouvelle application… » : choisir l'entreprise bac à sable Burger Queen et une application de délégation (authorization code) si le formulaire demande le type. . Redirect URL (l'adresse de rappel), exactement : +
http://localhost:8765/ext/SUPERPDP/oauth/callback
C'est la route de rappel de l'instance (superpdp:callback, /ext/SUPERPDP/oauth/callback, ui/bulma/bulma.cr), servie en local par l'essai sur le port 8765 (SUPERPDP_SANDBOX_OAUTH_PORT pour un autre port : déclarer alors ce port). L'essai affiche cette adresse s'il manque un identifiant. . Noter le client_id et le client_secret (affiché une seule fois) dans le fichier du poste (étape 3).
=== 2. Entreprise belge de test
. « Applications », puis « Nouvelle application… » : entreprise bac à sable Tricatel, application ordinaire (client credentials). Ses identifiants sont ceux de l'acheteur de la suite d'intégration (SUPERPDP_SANDBOX_BUYER_…) : la même application sert aux deux. . Cliquer sur Tricatel, puis « Nouvelle ligne d'annuaire… » : Scheme ID belge 0208 et un numéro d'entreprise de dix chiffres valide modulo 97 (huit chiffres, puis 97 moins leur reste par 97 : 1234567894, par exemple). L'inscription dans l'annuaire Peppol de test n'est pas automatique : sans cette ligne, l'essai s'arrête et le dit. . Dans le parcours de l'essai, autoriser Burger Queen, pas Tricatel : l'entreprise raccordée envoie la facture, Tricatel la reçoit.
=== 3. Identifiants sur le poste
Fichier ~/.config/partiduo/superpdp-sandbox.env (droits 600, jamais versionné), lignes VAR=valeur ; l'environnement est prioritaire, et SUPERPDP_SANDBOX_ENV_FILE désigne un autre fichier :
[source,sh]
Application OAuth bac à sable de l'opérateur (étape 1)
SUPERPDP_SANDBOX_OAUTH_CLIENT_ID= SUPERPDP_SANDBOX_OAUTH_CLIENT_SECRET=
Entreprise belge de test, Tricatel (étape 2)
SUPERPDP_SANDBOX_BUYER_CLIENT_ID= SUPERPDP_SANDBOX_BUYER_CLIENT_SECRET=
Facultatives : port de la route de rappel locale (8765), courriel
pré-rempli dans le parcours SUPER PDP
SUPERPDP_SANDBOX_OAUTH_PORT= SUPERPDP_SANDBOX_OAUTH_LOGIN_HINT=
Suite d'intégration (vendeur, Burger Queen en client credentials)
SUPERPDP_SANDBOX_SELLER_CLIENT_ID= SUPERPDP_SANDBOX_SELLER_CLIENT_SECRET=
=== 4. Essai de bout en bout en bac à sable
spec/integration/oauth_sandbox_essai.cr (nom sans _spec : jamais dans la suite) passe par le contrat de l'instance, comme l'écran « Se raccorder avec SUPER PDP » d'un dossier belge :
. l'instance génère le lien d'autorisation (state haché à usage unique, PKCE S256) ; l'essai l'affiche ; . vous l'ouvrez dans votre navigateur, ouvrez le compte, autorisez Burger Queen ; . SUPER PDP vous renvoie sur la route de rappel, servie en local par l'essai (15 minutes au plus) ; . l'instance échange le code (PKCE) contre les jetons et appelle GET /oauth2_sessions/me et GET /companies/me : raccordée, en bac à sable ; . l'entreprise raccordée envoie une facture UBL PEPPOL BIS (generate_test_invoice, format ubl-peppol-bis) adressée en 0208:<numéro> ; Tricatel la reçoit (GET /invoices?direction=in).
[source,sh]
createdb --encoding=UTF8 partiduo_test_oauth (cd ~/prod-partiduo/partiduo-superpdp && DATABASE_URL='postgres:///partiduo_test_oauth?host=/tmp' crystal spec --no-debug spec/integration/oauth_sandbox_essai.cr) dropdb partiduo_test_oauth
Sans identifiants, l'essai s'arrête aussitôt (exemple « en attente ») avec les variables manquantes et l'adresse de rappel à déclarer. Il passe par HTTPS_PROXY s'il est défini. Réussi, il lève B-SPDP-004 pour le bac à sable.
=== 5. Production
. Souscription Belgique et vérifications de l'entreprise de l'opérateur (« Dossiers belges », point 1). . « Applications », puis « Nouvelle application… », liée à l'entreprise de production ; Redirect URL : l'adresse de rappel de l'instance, +
https://<hôte de l'instance>/ext/SUPERPDP/oauth/callback
construite par l'instance à partir de son hôte (redirect_uri de Superpdp::Ui::Handler), ou celle de PARTIDUO_SUPERPDP_REDIRECT_URI quand l'adresse enregistrée diffère. Hors localhost, elle est en https (Linking.redirect_uri?). SUPER PDP compare l'adresse à celle de l'application : chaque dossier ayant son propre hôte, déclarer l'adresse de chaque instance raccordée si le formulaire en admet plusieurs, sinon une application par instance (D-SPDP-015). . Réglages de l'instance (src/superpdp/config.cr), dans son fichier d'environnement : ** PARTIDUO_SUPERPDP_OAUTH_CLIENT_ID, PARTIDUO_SUPERPDP_OAUTH_CLIENT_SECRET (les deux, sinon le mode n'est pas proposé) ; ** PARTIDUO_SUPERPDP_REDIRECT_URI (facultatif, voir ci-dessus) ; ** PARTIDUO_EINVOICING_KEY (64 caractères hexadécimaux, chiffrement des jetons par EINV ; sinon dérivée de MARTEN_SECRET_KEY). . Dans le dossier : Réglages, SUPER PDP, « Se raccorder avec SUPER PDP » (numéro d'entreprise et schéma be_numero_entreprise pré-remplis pour un dossier belge).
== Organisation
[source]
src/partiduo-superpdp.cr # point d'entrée du shard (métier, sans interface) src/partiduo-superpdp/cli.cr # migrations pour la ligne de commande src/superpdp/ ├── app.cr, manifest.cr # application Marten superpdp, manifeste SUPERPDP ├── config.cr, errors.cr # configuration de l'instance, erreurs de l'API ├── client.cr, oauth.cr # échanges authentifiés, OAuth 2.1 (PKCE, rotation, révocation) ├── mapping.cr # correspondances API SUPER PDP ↔ Einvoicing::Connector ├── connector.cr # l'adaptateur Superpdp::Connector ├── models/, migrations/ # tables superpdp_* ├── services/ # raccordement (interne) ├── api/ # contrat public Superpdp::Api └── locales/ # fr, en, nl, de, es, it, pt ui/bulma/ # interface Bulma (Superpdp::Ui), ADR-005 D4 spec/support/superpdp_platform.cr # SUPER PDP simulée spec/integration/sandbox_spec.cr # suite d'intégration contre le bac à sable réel spec/integration/oauth_sandbox_essai.cr # essai manuel de la délégation OAuth (hors suite)
== Composition dans une distribution
[source,crystal]
require "partiduo-ui-bulma/partiduo_ui" require "partiduo-superpdp" require "partiduo-document/ui/bulma" require "partiduo-einvoicing/ui/bulma" require "partiduo-superpdp/ui/bulma"
Marten.configure do |config| config.installed_apps = config.installed_apps + Document::INSTALLED_APPS + Document::Ui::INSTALLED_APPS + Einvoicing::INSTALLED_APPS + Einvoicing::Ui::INSTALLED_APPS + Superpdp::INSTALLED_APPS + Superpdp::Ui::INSTALLED_APPS end
Configuration de l'instance (mode authorization code) :
PARTIDUO_SUPERPDP_OAUTH_CLIENT_ID,PARTIDUO_SUPERPDP_OAUTH_CLIENT_SECRET: application OAuth déclarée par l'opérateur dans SUPER PDP ;PARTIDUO_SUPERPDP_REDIRECT_URI(facultatif) : adresse de retour enregistrée dans cette application, sinonhttps://<instance>/ext/SUPERPDP/oauth/callback.
Les secrets et jetons sont chiffrés par EINV (PARTIDUO_EINVOICING_KEY, sinon dérivée de MARTEN_SECRET_KEY).
== Développement local
shard.yml et shard.lock référencent les shards maison sur GitHub (aloli-crystal/* et aloli-partiduo/*), suivis par branche. Le verrou versionné ne contient aucune dépendance path: : les ports FreeBSD et la CI l'exigent.
Pour travailler sur les copies de travail voisines (../../prod-crystal/<nom> et ../partiduo-<dépôt>), lancer :
[source,sh]
scripts/override-local.sh
Le script génère un shard.override.yml local et non versionné (ignoré par git), installe les shards, puis remet shard.lock à son état versionné. Une copie de travail absente reste prise sur GitHub.
Pour régénérer le verrou versionné, supprimer d'abord l'override local :
[source,sh]
rm -f shard.override.yml SKIP_MARTEN_CLI_PRECOMPILATION=1 shards update scripts/override-local.sh # retour au mode local
== Commandes
[source,sh]
cd prod-crystal/partiduo/partiduo-superpdp SKIP_MARTEN_CLI_PRECOMPILATION=1 shards install createdb --encoding=UTF8 partiduo_test_ DATABASE_URL='postgres:///partiduo_test_?host=/tmp' crystal spec crystal run manage.cr -- genmigrations superpdp # modèles et migrations alignés crystal tool format src spec ui config manage.cr && bin/ameba
Les specs tournent contre une SUPER PDP simulée (spec/support/superpdp_platform.cr) qui reproduit les réponses documentées de l'OpenAPI SUPER PDP (1.35.0.beta), vérifiées contre le bac à sable.
La suite d'intégration spec/integration/sandbox_spec.cr tourne contre le vrai bac à sable quand les identifiants des deux entreprises fictives existent : SUPERPDP_SANDBOX_SELLER_CLIENT_ID, SUPERPDP_SANDBOX_SELLER_CLIENT_SECRET, SUPERPDP_SANDBOX_BUYER_CLIENT_ID, SUPERPDP_SANDBOX_BUYER_CLIENT_SECRET, dans l'environnement ou dans ~/.config/partiduo/superpdp-sandbox.env (lignes VAR=valeur ; SUPERPDP_SANDBOX_ENV_FILE pour un autre fichier) ; SUPERPDP_SANDBOX=off la désactive. Elle passe par HTTPS_PROXY s'il est défini. Ces secrets ne sont jamais affichés, journalisés ni versionnés.
== Licence
GNU Affero General Public License v3 ou ultérieure (voir LICENSE).
partiduo-superpdp
- 0
- 0
- 0
- 1
- 6
- 7 days ago
- September 27, 2026
GNU Affero General Public License v3.0
Tue, 27 Oct 2026 07:52:22 GMT