Charges sociales non modifiables : ChargeSociales::update() rejeté par PostgreSQL (42601) #87

Open
opened 2026-08-13 18:50:19 +02:00 by arcodange · 1 comment
Owner

Symptôme

Aucune charge sociale n'est modifiable sur le déploiement Arcodange. Toute soumission du formulaire d'édition /compta/sociales/card.php?id=N&action=edit échoue, y compris quand on ne touche qu'un seul champ :

Error ERROR: 42601: multiple assignments to same column "fk_user_modif"
LOCATION: process_matched_tle, rewriteHandler.c:1114

Dolibarr affiche sa page « erreur technique » et l'enregistrement reste inchangé. Aucun message métier, rien dans l'UI qui indique que l'édition est impossible : le formulaire s'ouvre et se soumet normalement.

Cause

ChargeSociales::update() construit un UPDATE qui affecte deux fois la même colonne fk_user_modif. MySQL/MariaDB acceptent cette syntaxe ; PostgreSQL la rejette (SQLSTATE 42601). Le déploiement Arcodange tourne sur PostgreSQL, d'où un bug invisible sur l'installation de référence upstream.

Portée — bornée

Test Résultat
Édition de la date d'échéance d'une charge (sandbox) 42601
Édition du montant seul d'une charge (sandbox) 42601
Création d'une charge fonctionne
Mise à jour d'un tiers via REST (PUT /thirdparties/N) fonctionne

Le défaut est donc propre à ChargeSociales, pas systémique. Il n'existe par ailleurs aucune API REST pour cet objet (/taxes, /socialcontributions, /chargesociales → « API not found »), donc aucune voie de contournement applicative.

Environnement : Dolibarr 22.0.4, PHP 8.2.30, PostgreSQL, Apache, Linux aarch64.

Conséquence opératoire

Une charge sociale est de fait immuable : sa date et son montant doivent être justes à la création. Documenté dans .claude/skills/dolibarr-sandbox-write/RUNBOOK_charges_sociales.md et reproduit par test/updateSocialCharge.ts, qui diagnostique l'erreur au lieu de la subir.

Impact courant

La charge n°1 en production (URSSAF 1re échéance, 493 €) porte la date 22/05/2026 — la date de débit bancaire — alors que l'échéance officielle est le 05/05/2026. L'écart masque un retard de paiement de 17 jours. Cette correction est bloquée par le présent bug.

Voies possibles

  1. Correction en base — un UPDATE ciblé sur llx_chargesociales.date_ech et periode. Contourne l'application ; à arbitrer, la doctrine du dépôt étant l'append-only.
  2. Patch local de ChargeSociales::update() dans l'image — dédoublonner l'affectation.
  3. Remontée upstream chez Dolibarr, avec ce cas de reproduction.
  4. Ne rien faire — le justificatif PDF attaché à la charge porte l'échéancier officiel et rétablit la vérité pour un lecteur.

Voir PR #86 pour le contexte complet et adc-009.

## Symptôme **Aucune charge sociale n'est modifiable** sur le déploiement Arcodange. Toute soumission du formulaire d'édition `/compta/sociales/card.php?id=N&action=edit` échoue, y compris quand on ne touche **qu'un seul champ** : ``` Error ERROR: 42601: multiple assignments to same column "fk_user_modif" LOCATION: process_matched_tle, rewriteHandler.c:1114 ``` Dolibarr affiche sa page « erreur technique » et l'enregistrement reste inchangé. Aucun message métier, rien dans l'UI qui indique que l'édition est impossible : le formulaire s'ouvre et se soumet normalement. ## Cause `ChargeSociales::update()` construit un `UPDATE` qui affecte **deux fois la même colonne** `fk_user_modif`. MySQL/MariaDB acceptent cette syntaxe ; **PostgreSQL la rejette** (SQLSTATE 42601). Le déploiement Arcodange tourne sur PostgreSQL, d'où un bug invisible sur l'installation de référence upstream. ## Portée — bornée | Test | Résultat | | --- | --- | | Édition de la **date d'échéance** d'une charge (sandbox) | ❌ 42601 | | Édition du **montant seul** d'une charge (sandbox) | ❌ 42601 | | **Création** d'une charge | ✅ fonctionne | | Mise à jour d'un **tiers** via REST (`PUT /thirdparties/N`) | ✅ fonctionne | Le défaut est donc **propre à `ChargeSociales`**, pas systémique. Il n'existe par ailleurs aucune API REST pour cet objet (`/taxes`, `/socialcontributions`, `/chargesociales` → « API not found »), donc **aucune voie de contournement applicative**. Environnement : Dolibarr 22.0.4, PHP 8.2.30, PostgreSQL, Apache, Linux aarch64. ## Conséquence opératoire **Une charge sociale est de fait immuable : sa date et son montant doivent être justes à la création.** Documenté dans `.claude/skills/dolibarr-sandbox-write/RUNBOOK_charges_sociales.md` et reproduit par `test/updateSocialCharge.ts`, qui diagnostique l'erreur au lieu de la subir. ## Impact courant La charge n°1 en production (URSSAF 1re échéance, 493 €) porte la date **22/05/2026** — la date de **débit bancaire** — alors que l'échéance officielle est le **05/05/2026**. L'écart masque un retard de paiement de 17 jours. Cette correction est bloquée par le présent bug. ## Voies possibles 1. **Correction en base** — un `UPDATE` ciblé sur `llx_chargesociales.date_ech` et `periode`. Contourne l'application ; à arbitrer, la doctrine du dépôt étant l'append-only. 2. **Patch local** de `ChargeSociales::update()` dans l'image — dédoublonner l'affectation. 3. **Remontée upstream** chez Dolibarr, avec ce cas de reproduction. 4. **Ne rien faire** — le justificatif PDF attaché à la charge porte l'échéancier officiel et rétablit la vérité pour un lecteur. Voir PR #86 pour le contexte complet et `adc-009`.
Author
Owner

Portée élargie : la note publique est bloquée elle aussi

Le tableau de portée initial était incomplet. Vérifié le 13/08 en sandbox :

Chemin Résultat
Édition de la date 42601
Édition du montant seul 42601
Note publique (note.php, update_note()) 42601
Création d'une charge
Pièce jointe (documents/upload)
Mise à jour d'un tiers via REST

update_note() passe par le même UPDATE : aucune écriture sur une charge sociale n'aboutit, quelle qu'elle soit.

Un faux positif à connaître

Un premier test avait conclu que le chemin des notes fonctionnait. C'était faux. La page de retour de Dolibarr ré-affiche le texte soumis, si bien qu'un contrôle « le texte est là » réussit sur un enregistrement qui n'a jamais eu lieu. La note n'avait pas persisté, constaté en relisant l'objet dans une navigation séparée.

Relire l'objet, jamais la page de retour. test/annotateObject.ts applique cette règle et refuse explicitement en nommant le bug.

Contournement appliqué (PR #90)

La charge n°1 porte désormais une note de correction en pièce jointe — le téléversement n'étant pas un UPDATE sur l'objet. Elle établit que le 22/05 est la date du prélèvement, que l'échéance officielle est le 05/05, que le règlement a eu 17 jours de retard, et que l'écart reste dans le même mois et le même exercice.

Doctrine retenue par l'opérateur : si une donnée fautive est déjà en production et sans incidence insurmontable sur l'exercice, on ne force pas la correction — on annote l'objet.

Ce qui reste

L'issue reste ouverte : le défaut amont n'est pas corrigé, seulement contourné. Une charge sociale demeure totalement figée — sa date et son montant doivent être justes à la création. Les trois autres voies restent sur la table : correction en base, patch de l'image, remontée upstream.

## Portée élargie : la note publique est bloquée elle aussi Le tableau de portée initial était incomplet. Vérifié le 13/08 en sandbox : | Chemin | Résultat | | --- | --- | | Édition de la date | ❌ 42601 | | Édition du montant seul | ❌ 42601 | | **Note publique** (`note.php`, `update_note()`) | ❌ **42601** | | Création d'une charge | ✅ | | Pièce jointe (`documents/upload`) | ✅ | | Mise à jour d'un tiers via REST | ✅ | `update_note()` passe par le même `UPDATE` : **aucune écriture sur une charge sociale n'aboutit**, quelle qu'elle soit. ### Un faux positif à connaître Un premier test avait conclu que le chemin des notes fonctionnait. **C'était faux.** La page de retour de Dolibarr ré-affiche le texte soumis, si bien qu'un contrôle « le texte est là » réussit sur un enregistrement qui n'a jamais eu lieu. La note n'avait pas persisté, constaté en relisant l'objet dans une navigation séparée. **Relire l'objet, jamais la page de retour.** `test/annotateObject.ts` applique cette règle et refuse explicitement en nommant le bug. ## Contournement appliqué (PR #90) La charge n°1 porte désormais une **note de correction en pièce jointe** — le téléversement n'étant pas un `UPDATE` sur l'objet. Elle établit que le 22/05 est la date du prélèvement, que l'échéance officielle est le 05/05, que le règlement a eu 17 jours de retard, et que l'écart reste dans le même mois et le même exercice. Doctrine retenue par l'opérateur : *si une donnée fautive est déjà en production et sans incidence insurmontable sur l'exercice, on ne force pas la correction — on annote l'objet.* ## Ce qui reste L'issue reste **ouverte** : le défaut amont n'est pas corrigé, seulement contourné. Une charge sociale demeure totalement figée — sa date et son montant doivent être justes à la création. Les trois autres voies restent sur la table : correction en base, patch de l'image, remontée upstream.
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: arcodange-org/erp#87