Ajoute la TVA (%) et calcule automatiquement le Montant TTC

Architecture : Montant HT reste saisi à la main, un nouveau champ TVA
(%) le complète, et Montant TTC = round(HT * (1 + TVA/100), 2) devient
une valeur calculée plutôt que saisie -- champ readonly dans le
formulaire (aperçu live en JS), calcul faisant foi côté serveur dans
figli_compta_ledger_node_presave().

Migration (update hooks 8004/8005) : Montant TTC n'est **jamais**
modifié pour les données historiques -- seul un TVA effectif est
rétro-calculé depuis HT/TTC existants et ajouté en tant que nouvelle
métadonnée (1498 lignes renseignées, 58 laissées vides faute de TTC
source). Précision du champ TVA fixée à 4 décimales après vérification
empirique sur les 1556 lignes existantes : reconstruire TTC = HT * (1 +
TVA/100) avec un taux arrondi à 4 décimales ne s'écarte du TTC réel que
pour 9 lignes (probables factures multi-taux), contre 74 à 2 décimales.

Garde-fou supplémentaire dans le presave : le recalcul du TTC ne se
déclenche que si HT ou TVA ont réellement changé par rapport à la
révision précédente (comparaison à $node->original) -- sans ça,
rouvrir une ancienne ligne migrée pour corriger un simple libellé
aurait silencieusement dérivé son TTC historique de ±0,01€ à cause de
l'arrondi du taux rétro-calculé, ce qu'interdit la règle du projet de
ne jamais corriger les données historiques.

Réorganisation du formulaire : N° Facture rejoint Client sur une même
ligne, Montant HT/TVA/Montant TTC forment la ligne suivante -- les
poids de champs doivent rester des entiers (Drupal tronque silencieusement
tout poids fractionnaire lors de la sauvegarde de l'affichage).
This commit is contained in:
2026-09-07 11:36:53 +02:00
parent f00f680143
commit b7490eb76a
9 changed files with 354 additions and 29 deletions
@@ -12,6 +12,7 @@ dependencies:
- field.field.node.ligne_comptable.field_notes
- field.field.node.ligne_comptable.field_numero_facture
- field.field.node.ligne_comptable.field_repartition
- field.field.node.ligne_comptable.field_tva
- field.field.node.ligne_comptable.field_type_ligne
- node.type.ligne_comptable
module:
@@ -47,7 +48,7 @@ content:
third_party_settings: { }
field_entree_liee:
type: entity_reference_autocomplete
weight: 2
weight: 4
region: content
settings:
match_operator: CONTAINS
@@ -57,7 +58,7 @@ content:
third_party_settings: { }
field_flag:
type: entity_reference_autocomplete_tags
weight: 8
weight: 10
region: content
settings:
match_operator: CONTAINS
@@ -67,21 +68,21 @@ content:
third_party_settings: { }
field_montant_ht:
type: number
weight: 3
weight: 5
region: content
settings:
placeholder: ''
third_party_settings: { }
field_montant_ttc:
type: number
weight: 4
weight: 7
region: content
settings:
placeholder: ''
third_party_settings: { }
field_notes:
type: string_textarea
weight: 6
weight: 9
region: content
settings:
rows: 5
@@ -97,7 +98,7 @@ content:
third_party_settings: { }
field_repartition:
type: paragraphs
weight: 5
weight: 8
region: content
settings:
title: Répartition
@@ -113,6 +114,13 @@ content:
collapse_edit_all: collapse_edit_all
duplicate: duplicate
third_party_settings: { }
field_tva:
type: number
weight: 6
region: content
settings:
placeholder: ''
third_party_settings: { }
field_type_ligne:
type: options_select
weight: 1
@@ -12,6 +12,7 @@ dependencies:
- field.field.node.ligne_comptable.field_notes
- field.field.node.ligne_comptable.field_numero_facture
- field.field.node.ligne_comptable.field_repartition
- field.field.node.ligne_comptable.field_tva
- field.field.node.ligne_comptable.field_type_ligne
- node.type.ligne_comptable
module:
@@ -55,7 +56,7 @@ content:
settings:
link: true
third_party_settings: { }
weight: 8
weight: 10
region: content
field_montant_ht:
type: number_decimal
@@ -66,7 +67,7 @@ content:
scale: 2
prefix_suffix: true
third_party_settings: { }
weight: 3
weight: 5
region: content
field_montant_ttc:
type: number_decimal
@@ -77,14 +78,14 @@ content:
scale: 2
prefix_suffix: true
third_party_settings: { }
weight: 4
weight: 7
region: content
field_notes:
type: basic_string
label: above
settings: { }
third_party_settings: { }
weight: 6
weight: 9
region: content
field_numero_facture:
type: string
@@ -102,7 +103,18 @@ content:
view_mode: default
link: ''
third_party_settings: { }
weight: 5
weight: 8
region: content
field_tva:
type: number_decimal
label: above
settings:
thousand_separator: ''
decimal_separator: .
scale: 2
prefix_suffix: true
third_party_settings: { }
weight: 6
region: content
field_type_ligne:
type: list_default
@@ -0,0 +1,25 @@
uuid: 9e9fc15c-9f7b-466a-bab0-fc6fe802a22f
langcode: en
status: true
dependencies:
config:
- field.storage.node.field_tva
- node.type.ligne_comptable
id: node.ligne_comptable.field_tva
field_name: field_tva
entity_type: node
bundle: ligne_comptable
label: 'TVA (%)'
description: ''
required: false
translatable: true
default_value:
-
value: 0.0
default_value_callback: ''
settings:
min: null
max: null
prefix: ''
suffix: ''
field_type: decimal
@@ -0,0 +1,20 @@
uuid: 92ad1651-ab19-4c60-ad8c-4824fd97ecc3
langcode: en
status: true
dependencies:
module:
- node
id: node.field_tva
field_name: field_tva
entity_type: node
type: decimal
settings:
precision: 8
scale: 4
module: core
locked: false
cardinality: 1
translatable: true
indexes: { }
persist_with_no_fields: false
custom_storage: false