Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions guides/chargebee.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import ZUGFeRDExample from '/snippets/workflows/chargebee/cb-zugferd.mdx'
import XRechnungExample from '/snippets/workflows/chargebee/cb-xrechnung.mdx'
import PeppolExample from '/snippets/workflows/chargebee/cb-peppol.mdx'
import DKPeppolExample from '/snippets/workflows/chargebee/cb-dk-peppol.mdx'
import FRExample from '/snippets/workflows/chargebee/cb-france.mdx'

## Introduction

Expand Down Expand Up @@ -369,6 +370,75 @@ For Invopop to update the invoice in Chargebee and trigger Chargebee's own email

---

### 🇫🇷 France

France runs two parallel flows, and which one an invoice takes depends on whether the customer is registered in the **Annuaire** (the French directory).

- Customers subject to VAT in France are handled through the [e-invoicing flow](/guides/fr-pa-invoicing#sending) for domestic B2B transactions, with [status updates](/guides/fr-pa-status) reported back throughout.
- Customers not subject to VAT in France — international or B2C transactions, and territories excluded from the mandate such as Guyane, Mayotte, New Caledonia and French Polynesia — go through [e-reporting](/guides/fr-pa-reporting) instead.

**Required apps:** [France](/apps/france), [Peppol](/apps/peppol), [OASIS UBL](/apps/oasis-ubl)

<Info>
Before processing any invoices, you must register your supplier in the Annuaire through Invopop. See the [registration guide](/guides/fr-pa-registration) for the e-invoicing flow and the [e-reporting registration steps](/guides/fr-pa-reporting#registration) for the reporting flow.
</Info>

{/* TODO: Add the walkthrough video once recorded, matching the other countries.
<iframe
className="w-full aspect-video rounded-xl"
src="https://www.youtube.com/embed/TODO_VIDEO_ID"
title="Chargebee + Invopop | E-invoicing in France"
frameBorder="0"
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowFullScreen
loading="lazy"
></iframe>
*/}

A single template covers both French flows and picks between them automatically from the result of the **Lookup in Directory** step.
- **found** result means the customer is subject to e-invoicing, so Invopop records the document in the Annuaire, forwards it to the PPF, and sends it over Peppol.
- **not found** result means the transaction falls outside domestic e-invoicing — international B2B, B2C, or a customer in a territory excluded from the mandate — so it is recorded for e-reporting. For those, the **Can Send** action checks whether the customer is reachable on the Peppol network: if it is (a Belgian party, for example), the workflow sends the invoice over Peppol as well.

<Tabs>
<Tab title="Template">
<Card title="Chargebee France" icon="code-branch" iconType="duotone" href="https://console.invopop.com/redirect/workflows/new?template=chargebee-cb-france" cta="Add to my workspace">
Syncs with Chargebee, looks the customer up in the French Annuaire, and branches automatically: registered parties are e-invoiced via Peppol France CIUS and forwarded to the PPF, while unregistered parties are recorded for e-reporting.
</Card>
</Tab>
<Tab title="Code">
<Note>
For a full walkthrough including required apps, directory registration, and customer routing, see the [France section of the Chargebee guide](/guides/chargebee#france).
</Note>

<Note>
The two paths differ in the addon and format they apply: the e-invoicing path applies the `fr-ctc-flow2-v1` addon and generates a Peppol France CIUS UBL, while the e-reporting path applies `fr-ctc-flow10-v1` and, when the customer is reachable on Peppol, generates a Peppol BIS Billing v3 document.
</Note>

<Note>
The **Add bank details** step includes placeholder `bic` and `iban` fields that you must fill in with your own banking details. It only applies when the invoice carries payment due dates and the payment key is a plain `credit-transfer`, normalizing it to the SEPA format France expects. If you don't need to include payment instructions, you can remove this step.
</Note>

<Note>
The **Add Billing Mode** step sets the French CTC billing mode: `S2` when the invoice is fully paid (an advance equal to the total), otherwise `S1`. The subsequent **Add VATEX** step maps UNTDID tax categories onto the GOBL tax keys and adds the `VATEX` exemption codes required by the French format.
</Note>
Comment thread
Copilot marked this conversation as resolved.
<FRExample />
</Tab>
</Tabs>

#### Customer routing &amp; identifiers

A single SIREN registered in the Annuaire can have several directory entries, registered under the same or different Plateformes Agréées. Each entry has a unique identifier — mapped to the Peppol inbox — in one of the `SIREN`, `SIREN_SIRET`, `SIREN_SIRET_suffix` or `SIREN_suffix` forms. When no Peppol inbox is set on the customer, Invopop defaults to `0225:SIREN`, ignoring any SIRET present in the customer's identities.

Use the custom fields below to control this. Set the **Peppol inbox** to target a specific directory entry, or provide the customer's **SIREN** and **SIRET** so the directory lookup can resolve them. All three are configured as **Single line text** custom fields (or as metadata, using the hyphenated key):

| Field | Metadata key | Custom field key | Example |
| ----- | ------------ | ---------------- | ------- |
| Peppol inbox | `gobl-customer-inbox-peppol` | `cf_gobl_customer_inbox_peppol` | `0225:123456789_test` |
| SIREN | `gobl-customer-identity-SIREN` | `cf_gobl_customer_identity_SIREN` | `123456789` |
| SIRET | `gobl-customer-identity-SIRET` | `cf_gobl_customer_identity_SIRET` | `12345678900011` |

---

## Retriggering Invoices

There may be situations where you need to reprocess an invoice. The method depends on whether Invopop has already created a silo entry (invoice) for it.
Expand Down
235 changes: 235 additions & 0 deletions snippets/workflows/chargebee/cb-france.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,235 @@
---
title: "Chargebee France send invoice"
description: "Sync from Chargebee and forward to PPF or record for reporting"
countryCode: "fr"
appId: "chargebee"
schema: "bill/invoice"
---

```json Example Chargebee France workflow
{
"name": "Chargebee France send invoice",
"description": "Send French invoice through Peppol network and to the PPF",
Comment thread
migueltorresvalls marked this conversation as resolved.
"schema": "bill/invoice",
Comment thread
methodofaction marked this conversation as resolved.
"steps": [
{
"id": "30960320-a44d-11f0-b23b-fd08a0f26c87",
"name": "Import Chargebee document",
"provider": "chargebee.import"
},
{
"id": "66cdc390-485f-11f1-86b7-9745cc4d2380",
"name": "Download PDF",
"provider": "chargebee.pdf.download"
},
{
"id": "33e23480-10ab-11f0-a09e-7b63571a4ae2",
"name": "Set state",
"provider": "silo.state",
"summary": "Set state to `processing`{.state .processing}",
"config": {
"state": "processing"
}
},
{
"id": "eea78ac0-26f0-11f1-9156-e518ebabd527",
"name": "Add billing mode",
"provider": "silo.modify",
"notes": "S2 (already-paid) ONLY when fully paid (totals.advance == total_with_tax); else S1. S2 also adds payment.terms due_dates (BR-FR-CO-09). Reads .totals.advance (NOT the old .advances bug).",
"summary": "Modifications configured",
"config": {
"jq": ".tax.ext = (.tax.ext // {})\n| .tax.point = \"issue\"\n| if ((.totals.advance // null) != null and (.totals.advance == .totals.total_with_tax)) then\n .tax.ext[\"fr-ctc-billing-mode\"] = \"S2\"\n | .payment = (.payment // {})\n | .payment.terms = (.payment.terms // {\"due_dates\":[{\"date\":.issue_date,\"percent\":\"100%\"}]})\n else\n .tax.ext[\"fr-ctc-billing-mode\"] = \"S1\"\n end",
"merge_type": "application/jq",
"scope": "doc"
}
},
{
"id": "4f427d80-a44d-11f0-b23b-fd08a0f26c87",
"name": "Add VATEX",
"provider": "silo.modify",
"summary": "Modifications configured",
"config": {
"jq": ".lines |= map(\n .taxes |= map(\n (.ext[\"untdid-tax-category\"]? as $cat\n | if $cat then\n {\n key: {\n \"AE\": \"reverse-charge\",\n \"E\": \"export\",\n \"G\": \"export\",\n \"O\": \"outside-scope\",\n \"K\": \"intra-community\"\n }[$cat],\n vatex: {\n \"AE\": \"VATEX-EU-AE\",\n \"G\": \"VATEX-EU-G\",\n \"O\": \"VATEX-EU-O\",\n \"K\": \"VATEX-EU-IC\"\n }[$cat]\n } as $m\n\n | if $m.key then .key = $m.key else . end\n | if $m.vatex then\n .ext = ((.ext // {}) + {\"cef-vatex\": $m.vatex})\n else\n .\n end\n else\n .\n end\n )\n )\n)",
"merge_type": "application/jq",
"scope": "doc",
"sign": false
}
},
{
"id": "7dad54c0-154a-11f0-8028-c1ed648b57b5",
"name": "Add bank details",
"provider": "silo.modify",
"notes": "Normalizes the payment key to SEPA credit transfer format",
"summary": "Modifications configured",
"config": {
"allow_invalid_json": false,
"data": {
"doc": {
"payment": {
"instructions": {
"credit_transfer": [
{
"bic": "",
"iban": ""
}
],
"key": "credit-transfer"
}
}
}
},
"expr": "(doc?.payment?.instructions == nil || doc?.payment?.instructions?.key == \"credit-transfer\")\n&& doc?.payment?.terms?.due_dates != nil",
"merge_type": "application/merge-patch+json",
"sign": false
}
},
{
"id": "fb06b190-10aa-11f0-a09e-7b63571a4ae2",
"name": "Sign envelope",
"provider": "silo.close"
},
{
"id": "de2407b0-5e94-11f1-90fe-f3d836f89160",
"name": "Lookup in Directory",
"provider": "gov-fr.directory.lookup",
"next": [
{
"status": "NA",
"code": "found",
"steps": [
{
"id": "3ffd50e0-5e95-11f1-90fe-f3d836f89160",
"name": "Modify Silo Entry",
"provider": "silo.modify",
"summary": "Modifications configured",
"config": {
"addons": [
"fr-ctc-flow2-v1"
]
}
},
{
"id": "1f8bf500-5e95-11f1-90fe-f3d836f89160",
"name": "Generate UBL document",
"provider": "ubl.generate",
"summary": "Peppol France CIUS UBL Invoice/CreditNote",
"config": {
"attach_invoice_pdf": false,
"doc_type": "peppol-fr-cius",
"private": false
}
},
{
"id": "9e22f4a0-485f-11f1-86b7-9745cc4d2380",
"name": "Record document for e-invoicing",
"provider": "gov-fr.directory.record"
},
{
"id": "285c9450-5e95-11f1-90fe-f3d836f89160",
"name": "Send Peppol document",
"provider": "peppol.send"
},
{
Comment thread
migueltorresvalls marked this conversation as resolved.
"id": "2d6926c0-5e95-11f1-90fe-f3d836f89160",
"name": "Forward document to PPF",
"provider": "gov-fr.directory.forward"
}
]
},
{
"status": "NA",
"code": "not-found",
"steps": [
{
"id": "5cff2420-7470-11f1-9deb-cda1ffc5317f",
"name": "Add flow10 addon",
"provider": "silo.modify",
"summary": "Modifications configured",
"config": {
"addons": [
"fr-ctc-flow10-v1"
]
}
},
{
"id": "3a023fc0-5e95-11f1-90fe-f3d836f89160",
"name": "Record document for reporting",
"provider": "gov-fr.reporting.record"
},
{
"id": "aaf85b90-6996-11f1-8722-e7a7821bd54f",
"name": "Verify invoice can be sent",
"provider": "peppol.has.inboxes",
"next": [
{
"status": "NA",
"code": "true",
"steps": [
{
"id": "afcc78e0-6996-11f1-8722-e7a7821bd54f",
"name": "Generate UBL document",
"provider": "ubl.generate",
"summary": "Peppol BIS Billing UBL Invoice/CreditNote V3",
"config": {
"attach_invoice_pdf": false,
"doc_type": "bis-invoice-v3",
"private": false
}
},
{
"id": "b798c790-6996-11f1-8722-e7a7821bd54f",
"name": "Send Peppol document",
"provider": "peppol.send"
}
]
},
{
"status": "NA",
"code": "false"
}
]
}
]
}
]
},
{
"id": "3037a310-10ab-11f0-a09e-7b63571a4ae2",
"name": "Set state",
"provider": "silo.state",
"summary": "Set state to `sent`{.state .sent}",
"config": {
"state": "sent"
}
},
{
"id": "354dbed0-a44d-11f0-b23b-fd08a0f26c87",
"name": "Update Chargebee",
"provider": "chargebee",
"config": {
"document_select": "xml"
}
}
],
"rescue": [
{
"id": "39513240-10ab-11f0-a09e-7b63571a4ae2",
"name": "Set state",
"provider": "silo.state",
"summary": "Set state to `error`{.state .error}",
"config": {
"state": "error"
}
},
{
"id": "38fd0b30-a44d-11f0-b23b-fd08a0f26c87",
"name": "Update Chargebee",
"provider": "chargebee",
"config": {
"document_select": "xml"
}
}
]
}

```