Technique

BR-CL-23 Factur-X : code unité UN/ECE invalide, correction XML CII

3 min de lecture Par FacturX API

Guide BR-CL-23 : corriger un unitCode invalide dans une facture Factur-X / EN16931, mapper les unités ERP vers UN/ECE Rec 20 et revalider.

BR-CL-23 apparaît quand l’unité de mesure d’une ligne de facture n’utilise pas un code accepté par les listes de codes EN16931. Dans les ERP français, la cause est presque toujours la même : le XML exporte un libellé métier (pièce, heure, kg, m2) au lieu d’un code normalisé UN/ECE.

Réponse courte

Dans un XML CII Factur-X, l’unité d’une ligne doit être portée par l’attribut unitCode de ram:BilledQuantity. La valeur attendue est un code de liste, par exemple :

UsageCode fréquent
unité / pièceC62
heureHUR
kilogrammeKGM
mètreMTR
mètre carréMTK
litreLTR

Si votre ERP exporte piece, pcs, heure, h, kg ou un code interne, mappez-le vers le code UN/ECE attendu avant validation.

Exemple d’erreur

<ram:SpecifiedLineTradeDelivery>
  <ram:BilledQuantity unitCode="piece">2</ram:BilledQuantity>
</ram:SpecifiedLineTradeDelivery>

Le XML est lisible pour un humain, mais piece n’est pas le code normalisé attendu. Correction :

<ram:SpecifiedLineTradeDelivery>
  <ram:BilledQuantity unitCode="C62">2</ram:BilledQuantity>
</ram:SpecifiedLineTradeDelivery>

Où se trouve le champ dans CII

Le champ concerné est le Business Term BT-130 : unité de mesure facturée.

XPath simplifié :

rsm:CrossIndustryInvoice
  /rsm:SupplyChainTradeTransaction
  /ram:IncludedSupplyChainTradeLineItem
  /ram:SpecifiedLineTradeDelivery
  /ram:BilledQuantity/@unitCode

Il est lié à BT-129, la quantité facturée.

Pourquoi l’erreur arrive

Les ERP stockent souvent l’unité dans une table métier :

Valeur ERPSensCode à produire
unitépièceC62
pcspièceC62
hheureHUR
heureheureHUR
kgkilogrammeKGM
mmètreMTR
m2mètre carréMTK
llitreLTR

Le problème n’est pas la quantité. Le problème est la traduction du référentiel ERP vers la liste attendue par EN16931.

Correction dans le mapping ERP

La correction robuste consiste à ajouter une table de mapping explicite.

const unitCodeMap: Record<string, string> = {
  unite: 'C62',
  piece: 'C62',
  pcs: 'C62',
  h: 'HUR',
  heure: 'HUR',
  kg: 'KGM',
  kilogramme: 'KGM',
  m: 'MTR',
  metre: 'MTR',
  m2: 'MTK',
  litre: 'LTR',
  l: 'LTR',
}

Puis refuser les unités non mappées :

function toUneceUnitCode(rawUnit: string): string {
  const normalized = rawUnit
    .trim()
    .toLowerCase()
    .normalize('NFD')
    .replace(/\p{Diacritic}/gu, '')

  const code = unitCodeMap[normalized]
  if (!code) {
    throw new Error(`Unité non mappée vers UN/ECE: ${rawUnit}`)
  }

  return code
}

Ne laissez pas passer silencieusement une unité inconnue. Sinon, l’erreur ressortira plus tard dans la validation.

Attention aux unités sectorielles

Certains métiers utilisent des unités moins évidentes :

  • journée homme ;
  • forfait ;
  • palette ;
  • lot ;
  • tonne ;
  • kilomètre ;
  • mètre cube ;
  • prestation.

Pour ces cas, choisissez un mapping métier stable avec l’équipe produit ou métier. Ne mappez pas tout vers C62 par facilité : cela rend la donnée structurée moins utile pour le destinataire.

Peut-on corriger automatiquement ?

Oui, si le mapping est déterministe.

Exemples sûrs :

  • kgKGM
  • heureHUR
  • pieceC62

Exemples ambigus :

  • forfait
  • prestation
  • lot
  • service

Ces valeurs peuvent parfois être C62, mais ce choix dépend du contexte métier. Un moteur de réparation sérieux doit éviter d’inventer si le mapping n’est pas fiable.

Vérification après correction

Après correction, relancez une validation EN16931 :

curl -sS -X POST https://api.facturxapi.com/api/v1/validate \
  -H "Authorization: Bearer $FACTURX_API_KEY" \
  -F "[email protected]" \
  | jq '.valid, .errors[]?.id'

Si BR-CL-23 disparaît mais qu’une règle de montant apparaît, vérifiez que la quantité (BT-129) et le prix unitaire (BT-146) restent cohérents avec le montant net de ligne (BT-131).

Articles liés

Continuer la lecture

Étape suivante recommandée

Vous voulez localiser l'unité qui déclenche BR-CL-23 ?

Voici ce que vous allez obtenir :

  • Ligne XML en cause
  • Valeur unitCode détectée
  • Suggestion de mapping si déterministe
  • Revalidation après correction