---
suivi: 1538
date: 2026-09-14
sujet: Libération RG hors agrégats marché
chantier: marches / retenues / liberation-rg
type: fix
statut: poussé
hash: 04266b39
fichiers:
  - app/Services/LiberationRgFactureService.php
  - app/Services/MarcheRetenuesEtatsService.php
  - app/Services/MarcheSyntheseFinanciereService.php
  - app/Services/MontantFactureSousTraitantService.php
  - app/Models/DepotFacture.php
  - resources/js/Pages/Marches/Show.vue
  - tests/Unit/LiberationRgFacture1535SourceTest.php
  - tests/Unit/LiberationRgFacture1538SourceTest.php
  - database/data/journal_mises_a_jour_post_2026_06_12.php
  - public/build/
  - docs/suivi/SUIVI_1538_liberation_rg_agregats_marche.md
---

# SUIVI #1538 — Libération RG hors agrégats marché

## PROMPT ENVOYÉ

FIX : la libération de RG ne doit pas compter comme du travail facturé.
Facturé HT = base reconstituée, pas le net à payer. Retenu RG net des
libérations NV1+. Plafond sans double déduction. Calcul facture #1537
inchangé. Marché (montant, taux, théoriques) inchangé. Pas de migration.
Rebase Vite. Push main.

## BASE GIT

HEAD = origin/main au départ du lot. Rebase Vite sur origin/main à jour
AVANT `npm run build` (zone commune Marches/Show.vue).

## FICHES LUES

- **#1537 LEÇON** — calcul de facture juste : base = (TTC + finitions +
  CIE − libération) ÷ (1 − %). NE PAS y toucher.
- **#1535 LEÇON** — plafond NV1+ (`etatRetenue !== null`). Conservé ici
  pour le retenu net, sinon plafond et affichage divergent.
- **#1534 §6** — « ne jamais diminuer montant_retenu » : **supersédé**
  par ce lot (le retenu affiché devient net).
- **#1321** — ne pas injecter la libération dans total_paye comme
  surplus ; ici on la retire du facturé/payé HT de la facture porteuse.

## SYNTHÈSE

### Mapping UI ↔ back

Aucun champ nouveau. Lecture seulement.

| Affichage | Valeur | Source |
| --- | --- | --- |
| Facturé HT | Σ HT travail | synthese.totaux.total_facture_ht / MFSTS |
| Retenu RG | prélevé − libéré NV1+ | etats.rg.montant_retenu |
| Libéré | payé + en cours NV1+ | montant_libere + montant_libere_en_cours |
| Reste à retenir | théorique − prélevé | etats.rg.restant |

### Statut d’acquisition (identique #1535)

Une libération est acquise dès `FactureStatutService::etatRetenue !== null`
soit **NV1 et au-delà** (payée = Retenue, NV1+ non payée = En cours).
Brouillons exclus.

### Formule plafond

disponible = etats.rg.montant_retenu (déjà net NV1+)
           + libération HT du dépôt courant si déjà NV1+

Pas de seconde soustraction des factures. Equivalent à l’ancien
prélevé − libérations des autres dépôts NV1+.

### Cas de référence MCH-2026-069 (sit. 13)

Sit. 13 comptée à 43 011,56 HT (base), plus au net 53 455,12 HT.
Retenu RG ≈ prélevé 11 182,18 − libéré 11 088,73 ≈ 93 HT.

## DÉPLOIEMENT-TEST

OVH : git pull origin main ; php artisan optimize:clear ; view:clear ;
journal:sync.

Validation manuelle (sqlite skipped).

## LEÇON

Agrégats marché : sommer la base reconstituée dès qu’une libération est
saisie, jamais le net à payer. Retenu affiché = prélevé − libéré NV1+,
restant = théorique − prélevé (le libéré ne « recrée » pas du restant
à retenir). Si le retenu est net, le plafond ne doit pas retrancher
une seconde fois les factures.
