---
suivi: 1191
date: 2026-08-04
sujet: Saisie facture — masquer retenues hors marché + poste obligatoire sans_marche
chantier: depot-factures
type: fix
statut: poussé
hash: 1f232f77
fichiers:
  - resources/js/Pages/DepotFactures/DepotFactureSaisieForm.vue
  - app/Http/Controllers/DepotFactureController.php
  - tools/diag/diag_hors_marche_poste_1191.php
  - database/data/journal_mises_a_jour_post_2026_06_12.php
  - public/build/
---

## PROMPT ENVOYÉ

SUIVI #1191 — FRONT LOGIQUE A (lot 3/4) : retirer 2 cases, masquer retenues hors
marché (UI + serveur), rétablir poste obligatoire sur sans_marche. Affichage /
validation uniquement — aucune écriture de données, aucune migration.
HEAD base = #1190 (`8037c17e`).

## FICHES LUES

- `SUIVI_1026_diag_rattachement_logique_a.md` — cartographie cases/watchers ;
  retenues hors marché non masquées ; #1031 a retiré l’exigence poste sur
  sans_marche ; LEÇON : fichier 9000 L + watchers → cartographier avant de toucher.
- `SUIVI_1188` — dette D toujours vivante ; série SaisieForm.
- `SUIVI_1189` / `SUIVI_1190` — ne pas casser Bloquer / 3 issues / filtre enseigne.

## SÉMANTIQUE RETENUE (sans_marche vs marche_id NULL)

| Indicateur | Sens | Retenues | Poste obligatoire |
|------------|------|----------|-------------------|
| `sans_marche=1` | « Marché non encore créé — à relier ultérieurement » | Masquées / refusées (pas de capture différée) | **Oui** (#1191) |
| `rattachement_poste_direct` (JSON) | « Pas de marché, rattacher à un poste » | Masquées / refusées | **Oui** (déjà) |
| `marche_id NULL` sans ces flags | Brouillons, FG, autres | Masquées si pas de marché réel ; refus serveur si retenues > 0 postées en PROGRAMMES sans marché/enveloppe | **Non** |

Décision affichage : `peutSaisirRetenuesMarche` = destination PROGRAMMES +
`marche_id` réel + pas hors marché. Les retenues « différées » pour un marché
à créer ne sont **pas** saisissables tant que le marché n’est pas relié
(mesure prod 04/08 : 0 retenue jamais enregistrée hors marché).

Question Robin (si on veut changer) : faut-il **autoriser** la saisie différée
des % RG/CP sur `sans_marche` avant liaison marché ? Aujourd’hui **non**.

## MESURE POSTES MANQUANTS

Base locale `_tmp_mariadb` : schéma OK sur `erp_immo_migrate_1113`, **0 ligne**
`depot_factures` → mesure impossible ici.

Script prod : `php tools/diag/diag_hors_marche_poste_1191.php`

À coller en sortie : liste `sans_marche=1 SANS poste` + `rattachement SANS poste`
(deviennent non modifiables à l’enregistrement). Aucune correction data.

## SYNTHÈSE

### Front
- Cases retirées ; options sentinelles dans le Select marché.
- Select poste si `horsMarcheProgrammes` (sans_marche **ou** rattachement).
- Watcher `sans_marche` : **ne plus** effacer le poste.
- RG/CP/Finitions/OPC (+ pénalités UI) derrière `peutSaisirRetenuesMarche`.
- CIE / cagnotte reste visible (hors du `v-if` retenues).
- Bloc reconstitution : détails reconstitués seulement si `hasRetenueUiActive` ;
  carte entière masquée hors marché sans CIE/pénalités → gain hauteur pour #1192.
- Payload brouillon : poste envoyé aussi pour `sans_marche` (bug corrigé).

### Serveur
- Poste obligatoire si `sans_marche` (révocation commentaire #1031).
- `assertAucuneRetenueHorsMarche` (RG/CP/OPC/finitions) — erreur 422 visible ;
  aussi si PROGRAMMES + marche_id NULL + pas d’enveloppe.
- Enveloppe : réutilise le même assert + CIE interdit.

## DÉPLOIEMENT-TEST

```text
git pull origin main
php artisan optimize:clear
php artisan view:clear
php artisan journal:sync
php tools/diag/diag_hors_marche_poste_1191.php
```

Pas de migrate. Coller sortie diag (liste sans poste).

Tests manuels :
1. Avec marché → 4 retenues proposées
2. Hors marché (sentinelle) → retenues absentes
3. API retenue hors marché → 422 visible
4. sans_marche sans poste → 422 visible
5. Calcul reconstitution inchangé (dépôt avec retenues)
6. 47 RG / 26 historiques intactes ; 1269 ouvrables

## LEÇON

Mesure prod des postes manquants **avant** d’exiger le poste : sans dump local,
le script doit tourner sur OVH et la liste est une décision Robin, pas un
data-fix Cursor. Ne pas cacher CIE dans le même `v-if` que les retenues marché.
