# DfProforma Shopware — Devis pro forma avec acceptation client et auto-conversion

> Ce que fait DfProforma Shopware 6.7 sait émettre des factures, des bons de livraison et des avoirs — mais pas de devis pro forma. Or dans la quasi-totalité des contextes…

- Page: <https://www.datafirefly.com/documentation/dfproforma-devis-shopware/>
- Langue: fr
- Mis à jour le: 2026-07-01
- Autres langues: [en](https://www.datafirefly.com/en/documentation/dfproforma-shopware-pro-forma-quote/index.md), [es](https://www.datafirefly.com/es/documentation/dfproforma-shopware-presupuesto-proforma/index.md), [de](https://www.datafirefly.com/de/documentation/dfproforma-shopware-proforma-angebot/index.md), [it](https://www.datafirefly.com/it/documentation/dfproforma-shopware-preventivo-proforma/index.md), [pl](https://www.datafirefly.com/pl/documentation/dfproforma-devis-shopware/index.md), [nl](https://www.datafirefly.com/nl/documentation/dfproforma-devis-shopware/index.md), [pt](https://www.datafirefly.com/pt/documentation/dfproforma-devis-shopware/index.md)
- Index: <https://www.datafirefly.com/documentation/llms.txt>

## Ce que fait DfProforma

Shopware 6.7 sait émettre des factures, des bons de livraison et des avoirs — mais pas de devis pro forma. Or dans la quasi-totalité des contextes B2B (équipement industriel, services aux entreprises, achats publics, ventes par appel d'offres), le client doit recevoir un document formel qu'il accepte _avant_ que la commande devienne ferme.

DfProforma comble ce manque sans bricoler : un véritable type de document Shopware natif `df_proforma`, sa propre plage de numérotation `PF{n}`, son template PDF brandé Twig, un workflow d'acceptation client autonome avec URL publique signée HMAC-SHA256, et une auto-conversion en commande dès que la transaction sous-jacente passe à l'état payé.

**En résumé :** le commercial génère un devis depuis la fiche commande dans l'admin, l'envoie par email, le client clique le lien, accepte en ligne sans compte Shopware, paie, et le devis bascule automatiquement en statut _Converti_. Aucun clic manuel post-paiement.

## Prérequis

- **Shopware** 6.7.0 ou supérieur (le plugin n'est pas rétro-compatible 6.6 en raison des refontes du système de documents)
- **PHP** 8.2 minimum
- **MySQL** 8.0+ ou **MariaDB** 10.6+
- Workers de messages Shopware actifs (recommandé pour la gestion automatique des expirations)
- Mail service Shopware configuré (SMTP fonctionnel pour les envois transactionnels)

## Installation

### 1. Téléverser le plugin

Depuis l'administration Shopware, allez dans _Extensions → Mes extensions → Téléverser une extension_, et sélectionnez le fichier `DfProforma-1.0.6.zip`.

### 2. Installer et activer

Dans la liste des extensions, cliquez _Installer_ puis _Activer_. Les migrations Shopware s'exécutent automatiquement et créent :

- La table SQL `df_proforma` et ses index sur `order_id`, `status`, `public_token`
- Le type de document `df_proforma` dans `document_type`
- La plage de numérotation `document_df_proforma` au format `PF{n}`, configurable
- Le template email transactionnel de base pour la génération, l'envoi et l'acceptation

### 3. Recompiler l'administration

Le plugin fournit un module Vite admin qui étend la fiche commande (`sw-order-detail-base`). Il faut recompiler le bundle d'administration global pour que l'onglet _Pro forma_ apparaisse :

```
bin/build-administration.sh
bin/console cache:clear
```

**Oublier cette étape** est la première cause de « l'onglet Pro forma n'apparaît pas sur la fiche commande » — pensez à recompiler après chaque mise à jour du plugin.

## Configuration

### Paramètres globaux

Depuis _Extensions → Mes extensions → DfProforma → Configurer_, vous accédez aux paramètres suivants :

- **Validité par défaut** — Nombre de jours pendant lesquels le lien d'acceptation reste valide (30 par défaut). Chaque devis peut surcharger cette valeur individuellement.
- **Auto-conversion à l'encaissement** — Activée par défaut. Désactivez-la si vous souhaitez conserver le contrôle manuel du basculement _Accepté → Converti_.
- **Nom de l'expéditeur** — Nom affiché comme expéditeur des emails transactionnels (par défaut : le nom du sales-channel).
- **Accent de marque du PDF** — Couleur d'accent utilisée dans le template PDF livré (bandeau d'en-tête, ligne de séparation, badge de statut).

### Configuration par sales-channel

Les paramètres ci-dessus peuvent être surchargés par sales-channel dans _Paramètres → Sales channels → [votre canal] → Configuration du plugin_. Utile si vous gérez plusieurs boutiques avec des politiques de validité différentes (par exemple 30 jours pour le B2C, 60 jours pour le B2B).

## Générer un devis pro forma

### Depuis la fiche commande (admin)

1. Ouvrez une commande dans _Commandes → Vue d'ensemble_
2. Cliquez sur l'onglet _Pro forma_ (à côté de _Documents_)
3. Cliquez _Générer un devis pro forma_
4. Le PDF est créé, le devis apparaît dans la liste avec un numéro `PF-…` et le statut _Brouillon_

### Depuis l'API admin

Trois endpoints sont exposés pour intégrer la génération dans vos workflows externes :

```
POST /api/_action/df-proforma/generate
Body: { "orderId": "…" }

POST /api/_action/df-proforma/mark-sent
Body: { "proformaId": "…" }

GET  /api/_action/df-proforma/by-order/{orderId}
```

Authentification standard OAuth2 admin de Shopware. Utile pour brancher DfProforma sur un CRM externe ou un pipeline d'automatisation.

## Envoyer un devis au client

### Email transactionnel

Depuis la liste des devis (onglet Pro forma de la fiche commande), cliquez l'icône enveloppe à côté du devis. Le module :

1. Passe le devis en statut _Envoyé_ (avec horodatage)
2. Envoie un email au client via le Mail Service Shopware, en utilisant le template `df_proforma_sent`, dans la langue du sales-channel
3. Joint le PDF du devis et inclut l'URL publique d'acceptation
4. Émet l'événement `ProformaGeneratedEvent` (déclencheur Flow Builder)

### URL publique d'acceptation

Chaque devis envoyé porte une URL de la forme :

```
https://votre-boutique.com/proforma/accept/{token}
```

Le token est chiffré et signé HMAC-SHA256 avec la clé secrète Shopware (`APP_SECRET` / `kernel.secret`). Impossible à forger ou à deviner. L'URL expire après la validité du devis (30 jours par défaut).

## Page publique d'acceptation client

Le client ouvre l'URL — **sans compte Shopware requis** (la page contourne l'authentification standard du compte client). Il voit :

- Un récapitulatif propre de la commande : lignes, prix, TVA, totaux, conditions
- Un bouton principal _Accepter ce devis_
- Un bouton secondaire _Décliner avec motif_
- La validité affichée (« Valable jusqu'au 20/06/2026 »)

À l'acceptation :

- Signature horodatée à la milliseconde et persistée en base
- Adresse IP client persistée pour preuve
- Statut passe à _Accepté_ avec l'historique de transition marqué
- Événement `ProformaAcceptedEvent` dispatché vers Flow Builder

En cas de refus, le champ _Motif_ est obligatoire — utile pour vos commerciaux qui peuvent recontacter le client avec une contre-proposition.

**Personnalisation :** la page d'acceptation utilise les blocs Twig standards du Storefront et hérite de votre thème. Vous pouvez surcharger `@DfProforma/storefront/page/account/proforma/quote.html.twig` depuis votre thème.

## Workflow de statuts

Six statuts couvrent l'intégralité du cycle de vie d'un devis :

- **Brouillon** — Devis créé mais pas encore envoyé au client
- **Envoyé** — Email envoyé, en attente de réponse client
- **Accepté** — Client a cliqué _Accepter_ sur la page publique
- **Décliné** — Client a cliqué _Décliner_ avec motif
- **Expiré** — Validité dépassée sans réponse (transition automatique via scheduled task)
- **Converti** — Commande sous-jacente payée, conversion automatique

Chaque transition est persistée avec date à la seconde, identifiant de l'acteur, type de déclencheur (_commercial_, _client_, _système_, _paiement_) et payload JSON pour les métadonnées libres. Vous pouvez reconstituer l'historique exact d'un devis à tout moment.

## Auto-conversion à l'encaissement

Le module enregistre un Subscriber sur l'événement `order_transaction.state.paid` de la machine à états Shopware. Quand une transaction bascule en _payée_ (Stripe, virement, PayPal, etc.), le Subscriber :

1. Cherche tous les devis pro forma au statut _Accepté_ rattachés à la commande
2. Les bascule en statut _Converti_
3. Marque l'historique de transition avec le type de déclencheur _paiement_

Aucune intervention humaine, aucun cron, aucun délai. Vos rapports commerciaux restent cohérents sans effort.

Pour désactiver l'auto-conversion (si votre équipe préfère un contrôle manuel), décochez l'option dans _Configuration du plugin → Auto-conversion à l'encaissement_.

## Flow Builder — événements Business Event

Deux événements standards Shopware sont émis par le module :

- `ProformaGeneratedEvent` — À la génération d'un devis (implémente `BusinessEventInterface`)
- `ProformaAcceptedEvent` — À l'acceptation par le client (implémente `BusinessEventInterface`)

Les deux apparaissent automatiquement dans la liste des déclencheurs du Flow Builder Shopware natif. Vous pouvez brancher dessus n'importe quelle action Flow :

- Notification Slack à l'équipe vente à l'acceptation
- Email récap interne au commercial responsable
- Webhook vers votre CRM (HubSpot, Salesforce, Pipedrive…)
- Mise à jour de champ personnalisé sur le client (par exemple, tag `quote-accepted`)
- Notification push mobile via un service tiers

Aucune intervention dans le code du module nécessaire — tout se configure depuis _Paramètres → Shop → Flow Builder_.

## Personnalisation du template PDF

Le PDF du devis est rendu via `DocumentFileRendererRegistry` (le nouveau système de rendu de fichiers Shopware 6.7), à partir du template Twig `@DfProforma/documents/proforma.html.twig` livré dans le module.

Pour le personnaliser, créez un plugin custom ou surchargez-le depuis votre thème en respectant la hiérarchie de templates Twig standard de Shopware :

```
custom/plugins/YourTheme/src/Resources/views/documents/proforma.html.twig
```

Le template livré expose ces blocs Twig identifiés :

- En-tête avec logo et coordonnées société
- Bloc client
- Récapitulatif des lignes de commande
- Totaux HT/TTC avec ventilation TVA
- Bandeau résumé en pied (numéro PF, dates d'émission et d'expiration)
- Filigrane _PRO FORMA_
- Accent de marque configurable via `config.accentColor`

Variables disponibles dans le template : `order` (OrderEntity chargée avec toutes ses associations), `config` (config du document dont `documentNumber`, `documentDate`, `validUntil`, `validityDays`), `context`.

## Multilingue

FR, EN, DE et ES sont livrés par défaut, snippets Storefront et Admin. Pour ajouter d'autres langues, créez un fichier de snippets par locale dans `src/Resources/snippet/` en suivant la convention Shopware standard.

Les templates email transactionnels sont également multilingues : le bon template est sélectionné automatiquement selon la langue du sales-channel du client au moment de l'envoi. Vous pouvez personnaliser les templates par langue depuis _Paramètres → Shop → Templates d'email_.

## API — endpoints admin disponibles

```
POST   /api/_action/df-proforma/generate         # Génère un devis pour une commande
POST   /api/_action/df-proforma/mark-sent        # Marque comme envoyé (transition manuelle)
GET    /api/_action/df-proforma/by-order/{id}    # Liste les devis d'une commande
```

Les entités `df_proforma` sont également accessibles via l'API DAL standard Shopware (`/api/df-proforma`) pour recherches, exports ou intégrations avancées.

## Désinstallation

Par défaut, les données métier sont conservées à la désinstallation (option _Keep User Data_ activée). Vous préservez ainsi l'historique d'audit des devis émis, utile pour la conformité et la traçabilité commerciale.

Pour forcer la suppression complète (table `df_proforma`, type de document, plage de numérotation, template email), désactivez l'option _Keep User Data_ dans le prompt de désinstallation.

**Recommandation :** gardez les données par défaut. Ne forcez la suppression que si vous êtes certain de ne plus jamais avoir besoin de remonter à l'historique des devis pour des raisons commerciales, comptables ou légales.

## Dépannage

### L'onglet Pro forma n'apparaît pas sur la fiche commande

Le bundle d'administration n'a pas été recompilé après installation. Lancez `bin/build-administration.sh` puis `bin/console cache:clear`.

### Erreur « Unable to find a document generator with type df_proforma »

Le tag de service du renderer n'est pas correct — ce bug est corrigé depuis la 1.0.2. Assurez-vous d'utiliser une version ≥ 1.0.2 du plugin.

### Erreur « Call to undefined method Context::getSalesChannelId() »

Cause historique : ancienne signature du constructeur `RenderedDocument`. Corrigé en 1.0.4. Mettez à jour vers 1.0.6.

### Erreur Twig « Cannot rewind a generator that was already run »

Corrigé en 1.0.6 — le template a été adapté pour ne pas consommer deux fois un générateur issu de `|filter()`.

### Le client reçoit l'email mais l'URL d'acceptation renvoie une erreur 404

Vérifiez que le sales-channel Storefront est bien enregistré comme domaine du canal de vente utilisé pour la commande. La route publique `/proforma/accept/{token}` est enregistrée sur le Storefront — elle ne fonctionne pas si vous accédez à l'URL via le domaine admin.

### L'expiration automatique ne fonctionne pas

Vérifiez que les _message workers_ Shopware sont bien lancés en arrière-plan (`bin/console messenger:consume` ou via un superviseur type systemd/supervisord). L'expiration passe par la file de messages Shopware standard.

## Support et mises à jour

12 mois de mises à jour incluses (compatibilité Shopware, corrections de bugs, ajouts fonctionnels mineurs). Support par email en français et anglais sous 24 heures ouvrées. Code source PHP livré en clair, conforme PSR-4, auditable et modifiable.

Pour toute question ou remontée : [contact@datafirefly.com](https://www.datafirefly.com/contact/).
