---
suivi: 1535
date: 2026-09-14
sujet: Libérer de la retenue de garantie depuis une facture
chantier: depot-factures / retenues / liberation-rg
type: feature
statut: poussé
hash: e83a83e9
fichiers:
  - app/Support/LiberationRgFactureSaisie.php
  - app/Services/LiberationRgFactureService.php
  - app/Services/DepotFacture/EcrituresComptablesCalculator.php
  - app/Support/FactureVentilationAffichagePresenter.php
  - app/Http/Controllers/ComptabilisationController.php
  - app/Http/Controllers/DepotFactureController.php
  - app/Http/Controllers/DemandeLiberationRgController.php
  - app/Services/DemandeLiberationRgService.php
  - app/Services/MarcheRetenuesEtatsService.php
  - resources/js/lib/depotFactureEcrituresCalculator.js
  - resources/js/Pages/DepotFactures/DepotFactureSaisieForm.vue
  - resources/js/Pages/DepotFactures/Index.vue
  - resources/js/Pages/Factures/Comptabilisation/Index.vue
  - resources/js/Pages/Marches/Show.vue
  - resources/js/Components/Marches/LiberationRgDemandesListe.vue
  - tests/Unit/DepotFactureEcrituresComptablesCalculatorTest.php
  - tests/Unit/LiberationRgFacture1535SourceTest.php
  - tests/Unit/ComptabilisationApbillLiberationRg1535Test.php
  - tests/Unit/ComptabilisationApbillRetenueTaxTest.php
  - database/data/journal_mises_a_jour_post_2026_06_12.php
  - public/build/
  - docs/suivi/SUIVI_1535_liberation_rg_facture.md
---

# SUIVI #1535 — Libération RG depuis une facture

## PROMPT ENVOYÉ

PHASE 2. Toute libération de RG passe par une facture (écriture Sage
réelle). Case distincte + montant TTC dans DepotFactureSaisieForm.
Injection APRÈS computeRetenuesGlobales. Ligne négative au décompte
(le net AUGMENTE). Plafond = MRES retenu − déjà libéré par factures ;
422 si dépassement. Marché obligatoire. Écran de demande : plus de
création, consultation conservée, demande 11 088,73 € inchangée.
États : retenu inchangé, colonne libéré distincte. Droits
m365GroupNames() brut. Exclure la ligne 401700 débit de la TVA APBILL.

## BASE GIT

HEAD = origin/main = e9c0e8c9 au départ du lot. `git fetch` : déjà à
jour. Rebase Vite sur origin/main à jour AVANT `npm run build`.

## FICHES LUES

- **#1534 LEÇON** — marquerPayee = drapeau sans Sage ; injecter APRÈS
  les globales, jamais dans le numérateur (pattern finitions L305
  interdit) ; débits 401 candidats charge #955 → exclure 401700 de la
  TVA ; statut/date_liberation du miroir inutilisables ; hors marché
  rien à libérer ; Gate::before fausse les tests admin.
- **#1521 LEÇON** — hors ERP : prélèvement possible, pas de suivi donc
  pas de libération.
- **#1321 LEÇON** — ne pas injecter la libération dans Total payé HT.

Aucune fiche #1533 n’a changé l’approche.

## SYNTHÈSE

### Mapping UI ↔ back

Libellé affiché | Valeur postée | JSON ocr_raw.saisie | Libellé back
--- | --- | --- | ---
Case « Libérer de la retenue de garantie » | bool | liberation_rg | checkbox, distincte de « Retenue de garantie » (%)
Montant à libérer (TTC) | float ≥ 0 | liberation_rg_montant_ttc | plafond comparé en HT via ttcVersHt

### Calcul

computeRetenuesGlobales inchangé. Après ST, crédit 401000 += TTC
libéré, rôle liberation_rg = débit 401700. hasRetenues ne comprend
pas la libération (pas de reconstitution 20 % induite).

### TVA APBILL — confirmation

La ligne de libération (rôle liberation_rg / débit 401700) **est
exclue** de la répartition de TVA. Elle reste candidate APBILL
(écriture 401700) avec tax_detail exonéré / tax_amount 0.00. Les
crédits de retenues restent exonérés comme avant.

### Plafond

etats.rg.montant_retenu (MRES, HT) − somme des liberation_rg_montant_ttc
des autres dépôts NV1+ du marché (TTC→HT). Les demandes_liberation_rg
(y compris 11 088,73 € Demandée) ne consomment PAS ce plafond.
Dépassement → 422 avec le disponible indiqué. Pas d’écrêtement.

### Droits

GS_COMPTABILITE, GS_ADMIN_ERP, GS_DSI via m365GroupNames() brut +
abort_unless si le montant change. Justification : la libération
augmente le net Sage ; trop large pour GS_HECTARE/GS_ENVOL seuls.
Changement de montant sans droit → 403. Case masquée hors périmètre.

### Demandes

store / payer / refuser → 410. Index et justificatifs conservés.
peut_demander = false, can_manage = false. Aucune reprise SQL.
Table demandes_liberation_rg conservée.

### États marché

montant_retenu inchangé. montant_libere + detail_liberation_rg
(facture, HT, état, intacct_bill_id). Pas d’injection dans
total_paye_ht.

## DÉPLOIEMENT-TEST

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

Tests manuels prod (sqlite skipped) : voir prompt cas 1–9.

## LEÇON

Libérer = rendre au fournisseur : débit 401700 + crédit 401000, jamais
dans le numérateur des %. Un débit 401 est candidat charge APBILL
(#955) : exclure explicitement la libération de la TVA, sinon Sage
répartit une quote-part sur le 401700. Plafond = MRES retenu −
factures NV1+, pas SUM(retenues_garantie) ni demandes Demandée.
Gate::before + hasAnyM365Group interdits pour ce droit.
