> Mise à jour du 25 septembre 2026 : voir le nouveau guide MEDIATHEQUE-ET-SUIVI.md pour le stockage en base et les documents.

# COPRO — Analyse et livraison des appels de fonds

Analyse du 24 septembre 2026, sur la copie `G:\SITES\_ACTIFS\COPRO`.

## Résultat livré

Les modifications portent sur les appels de fonds et leur transport SMTP. Accès : **Budget → Appel de fond → Préparer et envoyer les appels de fonds**.

Le nouveau parcours permet de :

- choisir un exercice et un trimestre ;
- créer les répartitions d’un exercice sans appels existants à partir du budget et des lots ;
- sélectionner plusieurs copropriétaires et préparer leurs PDF personnalisés ;
- vérifier chaque PDF et chaque email avant envoi ;
- envoyer les emails individuellement par SMTP, avec uniquement le PDF du destinataire ;
- retrouver les campagnes, PDF archivés et statuts d’envoi ;
- reprendre une campagne sans renvoyer automatiquement un appel déjà accepté par SMTP.

Chaque copropriété possède son IBAN et son modèle de la catégorie **Appels de fonds** : objet et message modifiables, avec variables `{prenom}`, `{nom}`, `{reference}`, `{copropriete}`, `{montant}`, `{echeance}`. Il s’agit d’une première catégorie opérationnelle, pas encore d’un gestionnaire de catégories couvrant tous les modules.

Un SMTP de plateforme est partagé. Les réponses sont dirigées vers le syndic de la copropriété. Le transport existant était déjà basé sur PHPMailer : il a été conservé et renforcé, sans dépendance WordPress et sans repli vers `mail()`.

## Première utilisation

1. Se connecter avec un compte gestionnaire ou syndic de la copropriété. Le nouveau module vérifie à la fois le niveau d’accès et le mandat en base (`mod_coproGest`, ou rôle `syndic` dans `mod_coproMbr`). Un compte global admin sans mandat local n’a pas automatiquement accès.
2. Ouvrir les paramètres du nouvel écran et renseigner l’IBAN, l’objet et le message. L’IBAN n’a pas été repris automatiquement depuis la valeur inscrite dans l’ancien code.
3. Vérifier les paramètres SMTP existants de `inc/config.php`, dans la section `smtp` : `hst`, `prt`, `eml`, `mdp`, `ncr`, éventuellement `from` et `nom`. `ncr` doit être `tls` ou `ssl`, avec le port adapté au fournisseur. Le certificat du serveur doit être valide.
4. Choisir l’année, le trimestre, l’échéance et la date d’arrêté des paiements. Pour un ancien exercice, adapter les dates.
5. Sélectionner les destinataires. Corriger d’abord les emails invalides. Préparer la campagne ; aucun email ne part pendant cette étape.
6. Vérifier les PDF, notamment la répartition et les soldes. Cocher la confirmation puis lancer l’envoi.
7. Garder la page ouverte pendant le traitement. En cas d’interruption, retrouver la campagne dans l’historique.

**Un statut SMTP accepté n’est pas une preuve de réception ou de lecture.** En cas d’échec ambigu, le renvoi automatique est bloqué : consulter le journal du serveur SMTP, puis utiliser « Résoudre après vérification » pour confirmer l’acceptation ou autoriser une reprise. Ce choix est journalisé.

## Calculs et protections

- Le nouveau calcul annuel répartit le budget au centime, avec répartition des centimes résiduels. Il ne duplique pas les lots lors de la lecture des clés spécifiques.
- Les trois premiers trimestres utilisent la division au centime inférieur ; le quatrième absorbe le reliquat. La somme annuelle reste exacte, même pour de très petits montants.
- Le solde inclut les appels des périodes antérieures au trimestre choisi, moins les recettes depuis `PLATEFORME_DATE_DEBUT` jusqu’à la date d’arrêté. Les crédits négatifs sont conservés.
- Les anciens appels ne sont pas réécrits. Un total incohérent avec son détail, des lignes dupliquées ou un historique non trimestriel bloquent la préparation : il faut vérifier les données comptables avant envoi.
- Une propriété ambiguë d’un lot bloque la création d’un nouvel exercice : il reste à désigner un destinataire comptable pour les indivisions et situations complexes.
- Génération annuelle en transaction ; création d’un exercice existant refusée.
- Autorisations contrôlées côté serveur, jetons CSRF pour les actions, échappement du contenu, PDF privés avec contrôle d’intégrité.
- Protection contre les doublons par copropriété, exercice, trimestre et membre, y compris entre campagnes et après rechargement.
- Les données du PDF et de l’email sont figées à la préparation. Modifier ensuite un modèle ou des coordonnées ne modifie pas une campagne déjà préparée.

La reprise des soldes antérieurs à la date de début de plateforme et l’historique des mutations de propriétaires ne sont pas reconstitués par cette livraison. Ils doivent être rapprochés des comptes réels avant utilisation.

## Installation et vérification

Aucune migration SQL n’est nécessaire. Le nouveau module utilise les tables existantes et stocke ses paramètres, PDF et journaux sous `var/appels/<coproId>/`, hors de `public`. Ce répertoire doit être accessible en écriture au processus PHP. Il doit être conservé lors des mises à jour : sa suppression ferait perdre les archives et la protection historique contre les renvois.

Le document root du site doit être le répertoire `public`. Une protection Apache a également été ajoutée à `var/.htaccess`.

Dompdf 3.1.6 et ses dépendances sont inclus sous `inc/pdf/vendor`, avec `composer.json` et `composer.lock`. L’installation suit la [documentation officielle de Dompdf](https://github.com/dompdf/dompdf#install-with-composer). Le module peut aussi utiliser le chemin externe `APPS_PDF` existant s’il est disponible. Le nouveau PDF n’utilise ni ressources distantes ni PHP embarqué.

Prévoir PHP 8.1 ou supérieur, PDO MySQL, DOM, mbstring, OpenSSL, et des tables transactionnelles pour bénéficier du rollback. Pour les tests isolés uniquement, PDO SQLite est nécessaire.

Vérifications effectuées :

- analyse syntaxique des fichiers PHP modifiés sous PHP 8.1 et 8.4 ;
- 29 contrôles d’intégration sur une base SQLite en mémoire, dont génération réelle de PDF, séparation entre copropriétés, protection des documents, incohérences comptables, reprise après échec et doubles envois ;
- 5 contrôles du transport SMTP, sans connexion réseau ;
- conservation des montants sur 1 000 valeurs annuelles ;
- rendu et contrôle visuel d’un vrai PDF A4 avec des données fictives.

Les tests sont fournis dans `tests/test_appels.php` et `tests/test_smtp.php`. `REAL_PDF=1` active la génération Dompdf réelle dans le premier test. Les comptes, la base de données et le serveur SMTP réels n’ont pas été utilisés. La compatibilité avec le schéma MySQL réel et un envoi de recette vers une boîte maîtrisée restent à valider sur l’hébergement.

La préparation est synchrone, limitée à 100 destinataires par campagne. Pour les grandes copropriétés ou un hébergement à faible limite de temps, faire des sélections plus petites ; une file de tâches serveur sera préférable à terme. L’envoi traite un destinataire par requête afin de limiter les interruptions.

## Autres corrections prioritaires avant ouverture à une deuxième copropriété

| Priorité | Constat dans le code | Modification recommandée |
|---|---|---|
| Critique | `inc/class.auth.php`, `formChangeMdp()` : lien de réinitialisation construit à partir de l’identifiant et d’une date encodés en Base64 ; pas de secret aléatoire validé côté serveur. | Remplacer par un jeton aléatoire à usage unique, expirant, stocké sous forme de hash. Le mécanisme actuel peut permettre une prise de compte. À corriger avant ouverture. |
| Critique | `_fonction.php`, `determinecopro()` : première copropriété trouvée, puis repli automatique sur l’identifiant 1. | Supprimer le repli, proposer un sélecteur des seules copropriétés autorisées et revalider le mandat à chaque requête. |
| Haute | `inc/class.formTraitement.php` charge des objets par identifiant seul et transmet des champs POST ; `module/copropriete/inc/copropriete.php` liste toutes les copropriétés. | Imposer le périmètre copropriété à toutes les lectures, modifications, suppressions et téléchargements. Ne jamais faire confiance au `coproId` envoyé par le navigateur. |
| Haute | Les mots de passe sont comparés et enregistrés avec SHA-1 dans `inc/class.auth.php`. | Migrer vers `password_hash`/`password_verify`, avec mise à niveau à la connexion ; renforcer aussi la gestion et la révocation des sessions. |
| Haute | La vérification CSRF du formulaire générique est facultative si le champ de jeton est absent. | Exiger un jeton valide sur chaque écriture, indépendamment de la présence du champ dans la requête. |
| Haute | Plusieurs valeurs issues des données sont injectées directement dans les vues ; affichage détaillé des erreurs activé dans `public/index.php`. | Échapper systématiquement les sorties et journaliser les erreurs côté serveur en production. |
| Haute | Le budget, les lots et les propriétaires sont des données courantes ; les anciennes fonctions de calcul contiennent des dates fixes et des règles d’arrondi différentes. | Versionner les budgets validés, dater la propriété des lots, définir un solde de reprise, rapprocher paiements et appels, poser des contraintes d’unicité et des clés étrangères. |
| Moyenne | `module/budget/infos.php` porte l’identifiant et le titre de la médiathèque ; anciennes classes et générateurs coexistent. | Corriger les métadonnées et supprimer les chemins obsolètes après validation, pour fiabiliser les permissions et la maintenance. |
| Moyenne | Catégories d’emails et historique ne sont pas centralisés à l’échelle de tous les modules. | Étendre le service à des catégories « appel de fonds », « relance », « assemblée », « message » et « compte », avec modèles versionnés, journaux et gestion des retours d’erreur. |
| Évolution | L’envoi groupé dépend d’une page ouverte et d’un stockage de fichiers sur un serveur. | Ajouter une file de tâches durable et un journal en base pour un déploiement sur plusieurs serveurs, avec limites de débit et reprise automatique des seuls échecs certains. |

Le nouveau parcours vérifie son propre périmètre copropriété. Cela ne sécurise pas automatiquement tous les autres modules. L’ouverture de la plateforme à une autre copropriété doit attendre en priorité les corrections d’authentification et d’isolation ci-dessus.

## Fichiers principaux livrés

- `public/appels.php` : nouvel écran et actions de préparation, téléchargement privé, envoi et résolution.
- `module/budget/inc/appels_service.php` : calculs, autorisations, PDF, archives et journal.
- `module/budget/inc/appeldefond.php` : accès au nouveau parcours ; un copropriétaire ne voit que sa propre répartition dans l’ancienne vue.
- `public/_assets/pdfgen/appeldefond_genere.php` : redirection de l’ancien générateur vers le parcours contrôlé.
- `inc/_smtp.php` : SMTP chiffré, validation des certificats, pièces jointes obligatoires, version texte et catégorie.
- `inc/pdf/` : dépendances PDF autonomes.
- `var/.htaccess`, `var/index.php` : protection du stockage.
- `tests/` : contrôles isolés.

Les anciennes méthodes de génération restent dans la classe historique pour éviter une refonte hors périmètre ; elles ne sont plus utilisées par les boutons du parcours administrateur. Aucun email réel envoyé, aucune base réelle modifiée, aucune sauvegarde créée.

