# cliArchiverCategoriesDocsLogements.php

Vide les catégories de documents de l'onglet **Documents de la fiche logement** en déplaçant
leurs fichiers vers une catégorie d'archivage unique (« Historique » par défaut), avec archivage
optionnel de la catégorie une fois vidée.

**Ne concerne que les documents LOGEMENT.** Les documents des locataires
(`categorie_document`, `documents`, `document_locataire`) ne sont jamais touchés.

## Ce qu'est un « document logement »

Contrairement aux documents locataires, un document logement **n'a aucune ligne en base** :
c'est uniquement un fichier posé sur le disque.

```
public/docs/logements/<idLogement>/uploads/<idCategorie>/<fichier>
public/docs/logements/<idLogement>/uploads/<fichier>          <- pseudo-catégorie « Sans catégorie »
```

Les catégories vivent dans `categorie_document_loge` (`id`, `nom`, `idParent`, `deleted`, `ordre`),
arbre plafonné à 3 niveaux par l'application (`fetchAllParents()` ne propose comme parent que les
catégories de `level < 2`).

**Déplacer un document = déplacer un fichier d'un dossier vers un autre.** Rien d'autre à
synchroniser, aucune ligne à mettre à jour.

## Utilisation

```bash
# 1) Voir ce qui se passerait, sur tout le parc (DRY-RUN, aucune écriture)
php5.6 cli/cliArchiverCategoriesDocsLogements.php --toutes

# 2) Cibler quelques catégories et lister chaque fichier
php5.6 cli/cliArchiverCategoriesDocsLogements.php --cat=1,5,18 --detail

# 3) Répétition à blanc sur un seul logement avant le grand soir
php5.6 cli/cliArchiverCategoriesDocsLogements.php --cat=1,5,18 --logement=352 --detail

# 4) Appliquer
php5.6 cli/cliArchiverCategoriesDocsLogements.php --cat=1,5,18 --go

# 5) Le tout : préfixe d'origine, archivage des catégories vidées, purge des dossiers, trace CSV
php5.6 cli/cliArchiverCategoriesDocsLogements.php --toutes --inclure-enfants --inclure-racine \
       --prefixer --supprimer-categorie --purger-dossiers --csv=/tmp/archivage.csv --go
```

Le script se lance **depuis la racine du projet** : il y lit `config/autoload/global.php` +
`local.php` pour la connexion, et `public/docs/logements` pour les fichiers.

## Paramètres

### Choix des catégories à vider (au moins un obligatoire)

| Paramètre | Effet |
|---|---|
| `--cat=<ids>` | ids séparés par des virgules (`--cat=1,5,18`) |
| `--cat-nom=<motif>` | catégories actives dont le nom correspond au `LIKE` SQL (`--cat-nom='DEVIS%'`) |
| `--toutes` | toutes les catégories actives, sauf la cible |
| `--inclure-enfants` | ajoute récursivement les sous-catégories des catégories choisies |
| `--inclure-racine` | traite aussi les fichiers posés directement dans `uploads/`, affichés sous « Sans catégorie » dans l'onglet |

Attention à la collation MySQL : `--cat-nom='%é%'` remonte aussi les noms contenant un `e`
(`utf8_general_ci` ne distingue pas les accents).

### Catégorie cible

| Paramètre | Effet |
|---|---|
| `--cible=<nom>` | défaut `Historique` ; si le nom n'existe pas, la catégorie est créée à la racine |
| `--cible=<id>` | utilise une catégorie existante (doit être active) |
| `--prefixer` | préfixe chaque fichier déplacé par sa catégorie d'origine |

Sans `--prefixer`, les fichiers gardent leur nom : tout arrive mélangé dans « Historique » et
l'origine est perdue. Avec, on obtient `ETAT_LIEUX__edl_2024-01-05-101500.pdf` (nom de catégorie
nettoyé : accents, `/`, apostrophes retirés).

### Après déplacement

| Paramètre | Effet |
|---|---|
| `--supprimer-categorie` | passe la catégorie vidée à `deleted = 1`, comme le fait l'application |
| `--purger-dossiers` | supprime en plus les dossiers source devenus vides sur le disque |

### Portée et sortie

| Paramètre | Effet |
|---|---|
| `--logement=<ids>` | limite le déplacement à ces logements |
| `--racine=<chemin>` | racine des documents (défaut `<projet>/public/docs/logements`) |
| `--db=<base>` | force la base (défaut : celle de `config/autoload/global.php`) |
| `--detail` | liste chaque fichier au lieu du seul résumé |
| `--csv=<fichier>` | trace complète des déplacements (UTF-8 avec BOM, séparateur `;`) |
| `--go` | **applique** ; sans lui, simulation |

## Garanties

* **DRY-RUN par défaut** : rien n'est écrit tant que `--go` n'est pas passé.
* **Aucun écrasement** : si un fichier du même nom existe déjà dans la cible, le nouveau reçoit
  un suffixe `_1`, `_2`… Le rapport annonce le nombre d'homonymes avant d'agir.
* **Aucune suppression de fichier** : uniquement des déplacements (`rename`, avec repli
  copie + vérification de taille + suppression si les systèmes de fichiers diffèrent).
* **Relançable** : un second passage ne trouve plus rien à déplacer.
* Les dossiers créés reprennent **droits et propriétaire de leur parent** : un script lancé en
  root ne casse pas les uploads suivants faits par Apache.

## Garde-fous (arrêt avant toute écriture)

* **Parent archivé, enfant oublié** : `getCategoriesTree()` descend depuis `idParent = 0`, une
  sous-catégorie dont le parent est `deleted = 1` n'est jamais atteinte et ses documents
  deviennent invisibles. Le script refuse de démarrer et propose `--inclure-enfants`.
* **Cible descendante d'une catégorie archivée** : même raison, la cible elle-même disparaîtrait.
* **Filtre `--logement`** : une catégorie n'est archivée que si elle est vide sur la **totalité**
  du parc, filtre compris. Si des fichiers restent ailleurs, elle est laissée active et le
  rapport le dit.

## Périmètre : uniquement `uploads/`

Le dossier d'un logement ne contient pas que des catégories de documents :

```
public/docs/logements/<idLogement>/
    uploads/                 <- SEUL dossier lu par le script
        <idCategorie>/       ...une par catégorie de `categorie_document_loge`
        <fichier>            ...pseudo-catégorie « Sans catégorie »
    edl-<idEDL>/             états des lieux (photos, signatures, edl.pdf) — jamais touché
    suivis/                  pièces jointes des multisuivis — jamais touché
    <fichier>                documents posés à ce niveau — jamais touché
```

Le script ne descend **que** dans `uploads/`, et n'y traite que les sous-dossiers dont le nom
est l'id d'une catégorie **lue en base** (`SELECT ... FROM categorie_document_loge`) : `--toutes`
part de la table, jamais du contenu du disque. `edl-*`, `suivis/` et les fichiers rangés
directement sous `<idLogement>/` ne sont ni listés, ni comptés, ni déplacés — le rapport le
rappelle en en-tête à chaque exécution.

## Anomalies signalées

Le rapport liste les dossiers `uploads/<n>` dont la catégorie est archivée ou a disparu de la
base : leurs documents existent sur le disque mais ne s'affichent nulle part dans l'onglet.
`--cat=<n>` permet de les récupérer vers la catégorie cible, même quand la ligne
`categorie_document_loge` n'existe plus.

Il signale aussi les sous-dossiers **non numériques** trouvés dans `uploads/` : ils n'ont pas été
créés par la gestion documentaire, le script les laisse strictement en place mais ne les passe
plus sous silence.

## Sortie CSV

```
idLogement;numeroLogement;idCategorieSource;nomCategorieSource;fichierSource;categorieCible;fichierCible;octets;statut
```

`statut` vaut `simule` en dry-run, sinon `deplace`, `echec`, `echec-dossier` ou `cible-existante`.

## Avant de lancer en production

```bash
# sauvegarde de la table des catégories
mysqldump -u root -p <base> categorie_document_loge > backup_categorie_document_loge_$(date +%F).sql
# sauvegarde des fichiers
tar czf backup_docs_logements_$(date +%F).tar.gz public/docs/logements
```

Le déplacement de fichiers n'est pas transactionnel : en cas d'interruption, les fichiers déjà
déplacés le restent. Le script étant relançable, il suffit de le relancer pour finir le travail.
