{"id":26165,"date":"2026-03-28T18:14:21","date_gmt":"2026-03-28T17:14:21","guid":{"rendered":"https:\/\/frnix.org\/contexte-dev\/"},"modified":"2026-04-23T11:06:38","modified_gmt":"2026-04-23T09:06:38","slug":"contexte-dev","status":"publish","type":"page","link":"https:\/\/frnix.org\/de\/contexte-dev\/","title":{"rendered":"Contexte Dev"},"content":{"rendered":"<details open>\n<summary>&#128221; v3.5.25-alpha &mdash; Help text wizard contact : champ organisation<\/summary>\n<p><strong>&#9989; Fix<\/strong><\/p>\n<ul>\n<li><code>class-wizard-schema.php<\/code> &mdash; champ <code>frnix_organization_id<\/code> : help text remplac&eacute; par <em>&laquo;&nbsp;Recherchez votre organisation, ou laissez vide.&nbsp;&raquo;<\/em>.<\/li>\n<li>Bump <strong>frnix-manager<\/strong> v3.5.24-alpha &rarr; v3.5.25-alpha (header + define FRNIX_VERSION)<\/li>\n<li>Bump <code>FRNIX_Wizard::VERSION<\/code> = &#39;3.5.25-alpha&#39;<\/li>\n<\/ul>\n<p><strong>&#129534; Justification<\/strong><\/p>\n<ul>\n<li>Ancien help text invitait &agrave; cocher <code>frnix_is_individuel<\/code>, mais ce champ est verrouill&eacute; admin-only depuis v3.5.24 &rarr; instruction obsol&egrave;te.<\/li>\n<li>Beaucoup de contacts FRNIX existants n&#39;ont pas d&#39;orga (consultants ind&eacute;pendants, &eacute;tudiants, externes). L&#39;absence d&#39;orga est un &eacute;tat l&eacute;gitime, pas une exception &agrave; signaler.<\/li>\n<\/ul>\n<\/details>\n<details open>\n<summary>&#128272; v3.5.24-alpha &mdash; Fix s&eacute;curit&eacute; : 4 switchers wizard contact gat&eacute;s + can_write_field corrig&eacute;<\/summary>\n<p><strong>&#128737;&#65039; Audit s&eacute;curit&eacute; (r&eacute;sum&eacute; v3.5.23-alpha)<\/strong><\/p>\n<ul>\n<li>4 switchers (frnix_is_individuel, contact_organisation, contact_votant, contact_facturation) &eacute;taient modifiables c&ocirc;t&eacute; serveur par un membre non-admin &eacute;ditant son propre profil via \/mon-profil\/.<\/li>\n<li>Cause : aucune cl&eacute; <code>writable_by<\/code> dans le sch&eacute;ma + bug dans <code>can_write_field<\/code> qui ne v&eacute;rifiait pas le r&ocirc;le r&eacute;el (juste mode=&#39;membre&#39; + valeur dans liste).<\/li>\n<li>Vecteur d&#39;attaque : aucun outil custom requis. Membre clique sur les switchers de son wizard, ajax accepte. Self-promotion Principal\/Votant\/Facturation\/Individuel possible.<\/li>\n<\/ul>\n<p><strong>&#9989; Fix v3.5.24 (Option B audit)<\/strong><\/p>\n<ul>\n<li><code>class-wizard-schema.php<\/code> &mdash; ajout <code>writable_by<\/code> sur 4 champs :\n<ul>\n<li><code>frnix_is_individuel<\/code> &rarr; <code>['admin']<\/code> (statut administratif)<\/li>\n<li><code>contact_organisation<\/code> &rarr; <code>['admin', 'org_editor']<\/code> (Principal d&eacute;l&egrave;gue)<\/li>\n<li><code>contact_votant<\/code> &rarr; <code>['admin', 'org_editor']<\/code><\/li>\n<li><code>contact_facturation<\/code> &rarr; <code>['admin', 'org_editor']<\/code><\/li>\n<\/ul>\n<\/li>\n<li><code>class-wizard-ajax.php::can_write_field()<\/code> &mdash; r&eacute;&eacute;crite pour v&eacute;rifier le r&ocirc;le r&eacute;el :\n<ul>\n<li><code>self<\/code> : exige <code>$current_uid === $entity_id<\/code> (type=contact)<\/li>\n<li><code>org_editor<\/code> : exige <code>manage_options<\/code> OU <code>is_principal_of_same_org()<\/code><\/li>\n<li>Default fallthrough chang&eacute; : <strong>true<\/strong> &rarr; <strong>false<\/strong> (plus d&eacute;fensif)<\/li>\n<li>Signature &eacute;tendue : <code>can_write_field($field, $mode, $entity_id, $type=&#39;contact&#39;)<\/code><\/li>\n<\/ul>\n<\/li>\n<li>Nouveau helper <code>FRNIX_Wizard_Ajax::is_principal_of_same_org($current_uid, $entity_id, $type)<\/code> &mdash; v&eacute;rifie meta <code>contact_organisation=&#39;true&#39;<\/code> + matching <code>frnix_organization_id<\/code>. G&egrave;re type=contact (compare orgas) et type=org (compare directement).<\/li>\n<li>Bump <strong>frnix-manager<\/strong> v3.5.23-alpha &rarr; v3.5.24-alpha (header + define FRNIX_VERSION)<\/li>\n<li>Bump <code>FRNIX_Wizard::VERSION<\/code> = &#39;3.5.24-alpha&#39;<\/li>\n<\/ul>\n<p><strong>&#129534; Validation 6 cas (mental + code review)<\/strong><\/p>\n<ul>\n<li>Membre lambda &rarr; son profil : 4 champs sensibles DENY &#9989;<\/li>\n<li>Principal &rarr; son propre profil : <code>contact_*<\/code> ALLOW (org_editor match), <code>frnix_is_individuel<\/code> DENY (admin only) &#9989;<\/li>\n<li>Principal &rarr; autre membre de son orga : <code>contact_*<\/code> ALLOW &#9989;<\/li>\n<li>Principal orga A &rarr; membre orga B : <code>can_edit<\/code> rejette au niveau entit&eacute; (avant champ) &#9989;<\/li>\n<li>Admin &rarr; n&#39;importe quel profil : ALLOW &#9989;<\/li>\n<li>Membre forge mode=&#39;membre&#39;\/&#39;admin&#39; via curl : DENY (vrais checks de r&ocirc;le) &#9989;<\/li>\n<\/ul>\n<p><strong>&#128203; TODO report&eacute; (non bloquant s&eacute;cu)<\/strong><\/p>\n<ul>\n<li>UX lecture-seule : afficher les switchers verrouill&eacute;s en disabled + help text contextuel (&laquo;&nbsp;Statut administratif g&eacute;r&eacute; par l&#39;&eacute;quipe FRNIX&nbsp;&raquo;, &laquo;&nbsp;D&eacute;sign&eacute; par d&eacute;cision de l&#39;organisation&nbsp;&raquo;, etc.). Estim&eacute; : 2-3 fichiers + JS state Alpine + template switcher conditionnel. <strong>Non trivial<\/strong> &rarr; report&eacute; en session ult&eacute;rieure. Le fix serveur (writable_by + can_write_field) suffit pour la s&eacute;curit&eacute; ; sans UX, le membre voit le switcher cliquable et l&#39;ajax retourne silencieusement (skip + 200, pas d&#39;erreur visible).<\/li>\n<li>Refactor mineur : <code>can_edit<\/code> et <code>can_write_field<\/code> dupliquent partiellement la logique \u00ab\u00a0is principal of same org\u00a0\u00bb. Pourrait factoriser via le nouveau helper <code>is_principal_of_same_org<\/code>.<\/li>\n<\/ul>\n<\/details>\n<details open>\n<summary>&#127912; v3.5.23-alpha &mdash; UI : bouton m&eacute;diath&egrave;que admin (texte court + tooltip)<\/summary>\n<p><strong>&#9989; Fix UI mineur<\/strong><\/p>\n<ul>\n<li><code>render-wizard.php:455<\/code> &mdash; Texte du bouton m&eacute;diath&egrave;que admin (&eacute;tat vide) raccourci de &laquo;&nbsp;Choisir depuis la m&eacute;diath&egrave;que FRNIX (admin)&nbsp;&raquo; &rarr; &laquo;&nbsp;M&eacute;diath&egrave;que FRNIX (admin)&nbsp;&raquo;.<\/li>\n<li>Ajout d&#39;un attribut <code>title=\"Choisir depuis la m&amp;eacute;diath&amp;egrave;que FRNIX (admin)\"<\/code> sur le bouton (tooltip au hover) pour conserver le texte explicite en accessibilit&eacute;.<\/li>\n<li>Bump <strong>frnix-manager<\/strong> v3.5.22-alpha &rarr; v3.5.23-alpha (header + define FRNIX_VERSION)<\/li>\n<li>Bump <code>FRNIX_Wizard::VERSION<\/code> = &#39;3.5.23-alpha&#39; (cache-bust assets, pour coh&eacute;rence)<\/li>\n<\/ul>\n<p><strong>&#128206; D&eacute;tails techniques<\/strong><\/p>\n<ul>\n<li>Patch via 2 str_replace cibl&eacute;s avec anchors ASCII (<code>@click.stop=&quot;openMediaPickerAdmin(field.key)&quot;&gt;<\/code> pour la position d&#39;insertion ; pr&eacute;fixe ASCII <code>&lt;i class=&quot;fas fa-photo-film&quot;&gt;&lt;\/i&gt; Choisir depuis la m<\/code> pour le texte). Aucun byte UTF-8 transit&eacute; via MCP, accents pr&eacute;serv&eacute;s.<\/li>\n<li>Title attribute en HTML entities (<code>m&amp;eacute;diath&amp;egrave;que<\/code>) plut&ocirc;t qu&#39;UTF-8 brut, par s&eacute;curit&eacute; transport. Render navigateur identique.<\/li>\n<li>Line ending CRLF d&eacute;tect&eacute; et pr&eacute;serv&eacute; pour la ligne ins&eacute;r&eacute;e.<\/li>\n<\/ul>\n<\/details>\n<details open>\n<summary>&#128737;&#65039; v3.5.22-alpha &mdash; Bug fix : URL admin TBB FRNIX hardcod&eacute;e (403)<\/summary>\n<p><strong>&#128030; Bug<\/strong><\/p>\n<ul>\n<li><code>\/wp-admin\/admin.php?page=frnix<\/code> renvoyait <strong>403<\/strong> pour les admins (ex : Fr&eacute;d&eacute;ric Eppendahl, login <code>studio<\/code>, role <code>administrator<\/code>).<\/li>\n<li>Diagnostic : ce n&#39;&eacute;tait PAS un probl&egrave;me de capability. Toutes les pages admin du plugin utilisent <code>manage_options<\/code> (cap WP standard), aucune cap custom n&#39;existe. Fr&eacute;d&eacute;ric a bien <code>manage_options<\/code>.<\/li>\n<li>Cause racine : URL hardcod&eacute;e fausse. Le menu slug r&eacute;el est <code>frnix-manager<\/code> (cf. <code>class-admin-page.php:1497-1505<\/code>), pas <code>frnix<\/code>. WP renvoie 403 g&eacute;n&eacute;rique pour tout slug non enregistr&eacute;.<\/li>\n<\/ul>\n<p><strong>&#9989; Fix<\/strong><\/p>\n<ul>\n<li><code>render-wizard.php:178<\/code> &mdash; <code>admin.php?page=frnix<\/code> &rarr; <code>admin.php?page=frnix-manager<\/code> (bouton &laquo; TBB FRNIX &raquo; du wizard frontend, admin only)<\/li>\n<li><code>frnix-mon-compte\/includes\/public-pages.php:432<\/code> &mdash; m&ecirc;me str_replace (origine du copy-paste vers render-wizard.php).<\/li>\n<li>V&eacute;rification post-patch : grep <code>page=frnix(?![a-z-])<\/code> sur tout le plugin &rarr; <strong>0 occurrence restante<\/strong>.<\/li>\n<li>Bump <strong>frnix-manager<\/strong> v3.5.21-alpha &rarr; v3.5.22-alpha (header + define FRNIX_VERSION)<\/li>\n<li>Bump <code>FRNIX_Wizard::VERSION<\/code> = &#39;3.5.22-alpha&#39; (cache-bust assets, par coh&eacute;rence m&ecirc;me si wizard.js inchang&eacute;)<\/li>\n<\/ul>\n<\/details>\n<details open>\n<summary>&#128279; v3.5.21-alpha &mdash; Lien &laquo;&nbsp;Mon tableau de bord&nbsp;&raquo; context-aware (admin impersonation)<\/summary>\n<p><strong>&#128030; Bug<\/strong><\/p>\n<ul>\n<li>Sur <code>\/mon-profil\/?admin_user_id=X<\/code> ou <code>\/mon-organisation\/?admin_org_id=Y<\/code> (admin impersonation), le bouton &laquo;&nbsp;Mon tableau de bord&nbsp;&raquo; en haut du wizard pointait toujours vers le TBB de l&#39;admin connect&eacute;, pas vers le TBB du contact\/orga &eacute;dit&eacute;.<\/li>\n<\/ul>\n<p><strong>&#9989; Fix<\/strong><\/p>\n<ul>\n<li><code>render-wizard.php:155-166<\/code> &mdash; logique de calcul de l&#39;URL TBB refaite, bas&eacute;e sur <code>$type<\/code> et <code>$entity_id<\/code> (d&eacute;j&agrave; en scope) au lieu du seul <code>$_GET[&#39;admin_user_id&#39;]<\/code> legacy.<\/li>\n<li>Cas g&eacute;r&eacute;s : (a) admin sur contact X &rarr; <code>\/mon-compte\/?admin_user_id=X<\/code> + label &laquo;&nbsp;TBB de [Pr&eacute;nom Nom]&nbsp;&raquo; ; (b) admin sur orga Y &rarr; <code>\/mon-organisation\/?admin_org_id=Y<\/code> + label &laquo;&nbsp;TBB de [titre orga]&nbsp;&raquo; ; (c) admin sur son propre profil &rarr; defaults inchang&eacute;s ; (d) membre normal &rarr; defaults inchang&eacute;s.<\/li>\n<li>Bump <strong>frnix-manager<\/strong> v3.5.20-alpha &rarr; v3.5.21-alpha (header + define FRNIX_VERSION)<\/li>\n<li>Bump <code>FRNIX_Wizard::VERSION<\/code> = &#39;3.5.21-alpha&#39; (cache-bust assets)<\/li>\n<\/ul>\n<p><strong>&#9881;&#65039; D&eacute;tails techniques<\/strong><\/p>\n<ul>\n<li>Patch via <code>substr_replace<\/code> par anchors ASCII pour pr&eacute;server le line ending <code>CRLF<\/code> du fichier (d&eacute;tect&eacute; runtime).<\/li>\n<li>Block remplac&eacute; : 760 bytes &rarr; 1 192 bytes (+432).<\/li>\n<li>Le legacy check <code>$_GET[&#39;admin_user_id&#39;]<\/code> est supprim&eacute; : couvert par <code>$entity_id<\/code> qui est d&eacute;j&agrave; mapp&eacute; depuis ce param par <code>class-wizard.php:121-122<\/code>. Pas de r&eacute;gression.<\/li>\n<\/ul>\n<\/details>\n<details open>\n<summary>&#128081; v3.5.20-alpha &mdash; Sidebar HappyFiles dans wp.media (frontend wizard, admin only)<\/summary>\n<p><strong>&#9989; Fait<\/strong><\/p>\n<ul>\n<li><code>class-wizard.php::enqueue_wizard_assets()<\/code> &mdash; ajout d&#39;un appel <code>&#92;HappyFiles&#92;Init::run()-&gt;setup-&gt;just_enqueue()<\/code> apr&egrave;s <code>wp_enqueue_media()<\/code>, gat&eacute; par <code>current_user_can(&#39;edit_users&#39;)<\/code> + triple guard (class_exists \/ isset \/ method_exists).<\/li>\n<li>Bump <strong>frnix-manager<\/strong> v3.5.19-alpha &rarr; v3.5.20-alpha (header + define FRNIX_VERSION)<\/li>\n<li>Bump <code>FRNIX_Wizard::VERSION<\/code> = &#39;3.5.20-alpha&#39; (cache-bust assets)<\/li>\n<\/ul>\n<p><strong>&#127919; Probl&egrave;me r&eacute;solu<\/strong><\/p>\n<ul>\n<li>HappyFiles ne hooke que <code>admin_enqueue_scripts<\/code>. En frontend, sa m&eacute;thode <code>has_media_modal()<\/code> ne tourne pas &rarr; sidebar HappyFiles invisible dans le modal wp.media du wizard frontend.<\/li>\n<li>Solution : utiliser le pattern HappyFiles natif <code>just_enqueue()<\/code> (m&ecirc;me hook que celui d&eacute;j&agrave; pr&eacute;vu pour Beaver Builder, BeTheme, Cornerstone &mdash; voir <code>setup.php<\/code> constructeur L25-31).<\/li>\n<li>Avantage : <code>wp_localize_script(&#39;happyfilesData&#39;)<\/code> + tous les enqueues d&eacute;pendants (dashicons, jquery) g&eacute;r&eacute;s automatiquement.<\/li>\n<\/ul>\n<p><strong>&#128683; Hors-scope<\/strong><\/p>\n<ul>\n<li>Pas touche &agrave; <code>wp.media({...})<\/code> dans <code>wizard.js<\/code> &mdash; les <code>frame: &#39;select&#39;<\/code> + <code>state: &#39;library&#39;<\/code> de v3.5.19 restent.<\/li>\n<li>Choix de <code>edit_users<\/code> (et non <code>upload_files<\/code>) pour rester coh&eacute;rent avec le gate admin existant L314.<\/li>\n<\/ul>\n<\/details>\n<details open>\n<summary>&#127919; v3.5.19-alpha &mdash; HappyFiles dans wp.media picker admin<\/summary>\n<p><strong>&#9989; Fait<\/strong><\/p>\n<ul>\n<li><code>wizard.js<\/code> &mdash; <code>openMediaPickerAdmin()<\/code> : ajout de <code>frame: &#39;select&#39;<\/code> + <code>state: &#39;library&#39;<\/code> dans l&#39;objet <code>wp.media({...})<\/code> pour activer la sidebar HappyFiles dans le modal admin.<\/li>\n<li>Bump <strong>frnix-manager<\/strong> v3.5.18-alpha &rarr; v3.5.19-alpha (header + define FRNIX_VERSION)<\/li>\n<li>Bump <code>FRNIX_Wizard::VERSION<\/code> = &#39;3.5.19-alpha&#39; (cache-bust assets wizard.js)<\/li>\n<\/ul>\n<p><strong>&#127919; Probl&egrave;me r&eacute;solu<\/strong><\/p>\n<ul>\n<li>Avant : <code>library: { type: &#39;image&#39; }<\/code> seul d&eacute;sactivait les int&eacute;grations tierces &rarr; sidebar HappyFiles invisible &rarr; impossible de retrouver un logo parmi 2000+ m&eacute;dias.<\/li>\n<li>Apr&egrave;s : le state <code>library<\/code> explicite r&eacute;active les onglets HappyFiles dans le picker.<\/li>\n<\/ul>\n<p><strong>&#9888;&#65039; Si le fix ne suffit pas (test &agrave; faire en local)<\/strong><\/p>\n<ul>\n<li>Fallback document&eacute; : retirer enti&egrave;rement <code>library<\/code> de l&#39;objet et filtrer apr&egrave;s <code>frame.open()<\/code> via <code>frame.state().get(&#39;library&#39;).props.set({type:&#39;image&#39;})<\/code>.<\/li>\n<\/ul>\n<\/details>\n<details open>\n<summary>&#128230; v3.5.18-alpha &mdash; Wizard contact : last_name required (PROD)<\/summary>\n<p><strong>&#9989; Fait<\/strong><\/p>\n<ul>\n<li>schema_contact() : champ <code>last_name<\/code> passe en <code>required = true<\/code><\/li>\n<li>Help text reformul&eacute; : <em>Pour un contact de type service, utilisez par exemple first_name=&#39;Service&#39; et last_name=&#39;Facturation&#39;.<\/em><\/li>\n<li>Bump <strong>frnix-manager<\/strong> v3.5.17-alpha &rarr; v3.5.18-alpha (header + define FRNIX_VERSION)<\/li>\n<li>Bump <code>FRNIX_Wizard::VERSION<\/code> = &#39;3.5.18-alpha&#39; (cache-bust assets wizard.js \/ wizard.css)<\/li>\n<\/ul>\n<p><strong>&#9888;&#65039; &Eacute;cart document&eacute; (TODO refonte registrations)<\/strong><\/p>\n<ul>\n<li><code>class-pending-registrations.php:805<\/code> &mdash; <code>if (empty($first_name) &amp;&amp; empty($last_name))<\/code> laisse passer <code>last_name<\/code> vide si <code>first_name<\/code> pr&eacute;sent. Concerne le <em>formulaire public d&#39;inscription<\/em>, pas le wizard admin.<\/li>\n<li>&Agrave; aligner lors de la session refonte email \/ pending.<\/li>\n<\/ul>\n<\/details>\n<details>\n<summary>Session 18 avril 2026 \u2014 Wizard FRNIX v1.0.11-alpha \u2014 Sprint majeur (BIS uniquement)<\/summary>\n<p><strong>Module wizard complet d&eacute;ploy&eacute; sur BIS<\/strong><\/p>\n<ul>\n<li>Mode admin\/membre : 100% fonctionnel<\/li>\n<li>Mirroring r&ocirc;les valid&eacute; (5\/5 sc&eacute;narios)<\/li>\n<li>&Eacute;tape 7 Contacts rattach&eacute;s (list\/attach\/detach\/create)<\/li>\n<li>Cycle retour orga apr&egrave;s &eacute;dition contact (save + redirect &eacute;tape 7)<\/li>\n<li>Clic libre sur puces en mode admin<\/li>\n<li>Lien parent_org dans header contact<\/li>\n<li>last_name auto-fill NC pour entit&eacute;s morales<\/li>\n<\/ul>\n<p><strong>Fix bugs<\/strong><\/p>\n<ul>\n<li>UTF-8 encoding, unicode escapes, autocomplete org, MIME FontAwesome, validation m&eacute;dia legacy<\/li>\n<\/ul>\n<p><strong>&Agrave; faire next<\/strong><\/p>\n<ul>\n<li>Mode qualification pour Samuel (460 orgas)<\/li>\n<li>NON d&eacute;ploy&eacute; sur PROD &mdash; validation BIS en cours<\/li>\n<\/ul>\n<\/details>\n<details>\n<summary>\ud83d\uddd3\ufe0f Session 16 avril 2026 \u2014 frnix-manager v3.2.3 \u2192 v3.2.7<\/summary>\n<h4>Versions d\u00e9ploy\u00e9es<\/h4>\n<ul>\n<li><strong>frnix-manager<\/strong> v3.2.3 \u2192 v3.2.7 (prod + bis)<\/li>\n<li><strong>frnix-events-manager<\/strong> : inchang\u00e9 v1.3.71<\/li>\n<\/ul>\n<h4>Corrections critiques<\/h4>\n<ul>\n<li>Fix enable-app-passwords.php manquant sur BIS \u2192 routes REST restaur\u00e9es (569 routes vs 48)<\/li>\n<li>render-unified-tables.php corrompu (handler frnix_bulk_invite avec CSS inject\u00e9) \u2192 fichier reconstruit complet<\/li>\n<\/ul>\n<h4>Nouvelles fonctionnalit\u00e9s<\/h4>\n<ul>\n<li>Fiche orga publique : tous les contacts rattach\u00e9s affich\u00e9s (plus de filtre sur les r\u00f4les)<\/li>\n<li>Email sous le nom dans la fiche orga (14px) pour identifier les doublons<\/li>\n<li>Modale admin \u00ab\u00a0Contacts\u00a0\u00bb refaite from scratch : tableau avec avatar, P\/F\/V checkboxes, Contacter\/Voir\/D\u00e9tacher, ajout contact, tri alphab\u00e9tique<\/li>\n<li>Colonne \u00ab\u00a0Inscrit le\u00a0\u00bb triable dans tableau contacts admin<\/li>\n<li>Colonne \u00ab\u00a0Cr\u00e9\u00e9e le\u00a0\u00bb triable dans tableau organisations admin<\/li>\n<li>Bouton \u00ab\u00a0\u2190 Tableau de bord FRNIX\u00a0\u00bb sur toutes les pages admin<\/li>\n<li>Lien \u00ab\u00a0Gestion des \u00e9v\u00e9nements\u00a0\u00bb pointe vers frnix-manager&amp;tab=events<\/li>\n<li>Widget \u00ab\u00a0Comptes \u00e0 valider\u00a0\u00bb ajout\u00e9 sur l&rsquo;onglet stats du dashboard<\/li>\n<li>Suppression page frnix-administration (add_submenu_page comment\u00e9, redirections mises \u00e0 jour)<\/li>\n<\/ul>\n<h4>Corrections comportement<\/h4>\n<ul>\n<li>Contact principal : requ\u00eate corrig\u00e9e pour lire contact_organisation=&rsquo;true&rsquo; (au lieu de frnix_role_principal=&rsquo;1&prime;)<\/li>\n<li>Notifications r\u00f4les P\/F\/V : d\u00e9sactiv\u00e9es quand modification par admin, actives quand modification par membre orga<\/li>\n<li>Nouvelles orgas cr\u00e9\u00e9es via \u00ab\u00a0Comptes \u00e0 valider\u00a0\u00bb : cat\u00e9gorie non_membre par d\u00e9faut + jamais masqu\u00e9es<\/li>\n<li>Anti-doublon cr\u00e9ation orga : bouton d\u00e9sactiv\u00e9 imm\u00e9diatement au clic<\/li>\n<li>Redirections frnix-administration remplac\u00e9es par frnix-organisations dans tous les fichiers<\/li>\n<li>Orgas sans cat\u00e9gorie en base : 33 mises \u00e0 jour \u2192 non_membre<\/li>\n<li>Alan Chollet IELO : entr\u00e9e pending #649 r\u00e9solue (d\u00e9j\u00e0 rattach\u00e9 \u00e0 org)<\/li>\n<li>Hook updated_user_meta : nettoyage auto des pending quand frnix_organization_id est mis \u00e0 jour<\/li>\n<li>Scan wp_user : rattachement auto des users dont le domaine email correspond \u00e0 une orga existante<\/li>\n<li>Inscription \u00e9v\u00e9nement : fallback domaine email pour d\u00e9terminer statut membre<\/li>\n<li>Filtre get_pending() : exclut les emails d\u00e9j\u00e0 rattach\u00e9s \u00e0 une organisation<\/li>\n<li>9 organisations masqu\u00e9es (_frnix_hidden) d\u00e9masqu\u00e9es (dont doublons AIRBUS, Etherlinx)<\/li>\n<\/ul>\n<h4>Fichiers modifi\u00e9s<\/h4>\n<ul>\n<li>frnix-manager\/frnix-manager.php<\/li>\n<li>frnix-manager\/includes\/modules\/admin\/render-unified-tables.php<\/li>\n<li>frnix-manager\/includes\/modules\/admin\/class-admin-page.php<\/li>\n<li>frnix-manager\/includes\/modules\/admin\/class-dashboard-entries.php<\/li>\n<li>frnix-manager\/includes\/modules\/admin\/class-admin-administration.php<\/li>\n<li>frnix-manager\/includes\/modules\/admin\/render-inscrits.php<\/li>\n<li>frnix-manager\/includes\/modules\/admin\/render-new-contact.php<\/li>\n<li>frnix-manager\/includes\/modules\/admin\/render-new-org.php<\/li>\n<li>frnix-manager\/includes\/class-pending-registrations.php<\/li>\n<li>frnix-manager\/includes\/class-official-contact.php<\/li>\n<li>frnix-manager\/frnix-mon-compte\/includes\/render-organisation.php<\/li>\n<li>frnix-manager\/frnix-mon-compte\/includes\/ajax-handlers.php<\/li>\n<li>frnix-events-manager\/includes\/class-form-handler.php<\/li>\n<li>frnix-events-manager\/includes\/class-admin-page.php<\/li>\n<li>frnix-events-manager\/includes\/class-history-page.php<\/li>\n<\/ul>\n<\/details>\n<details>\n<summary>\ud83d\uddd3\ufe0f Session 12 avril 2026 \u2014 frnix-manager v3.1.3 \u2192 v3.2.1<\/summary>\n<h4>Versions d\u00e9ploy\u00e9es<\/h4>\n<ul>\n<li><strong>frnix-manager<\/strong> v3.1.3 \u2192 v3.2.1 (prod)<\/li>\n<li><strong>frnix-events-manager<\/strong> : inchang\u00e9 v1.3.71<\/li>\n<\/ul>\n<h4>Corrections bugs (v3.1.4 \u2192 v3.1.9)<\/h4>\n<ul>\n<li>Emails <code>+tag@<\/code> accept\u00e9s tels quels \u00e0 l&rsquo;inscription<\/li>\n<li>Cycle de validation des comptes supprim\u00e9 \u2014 <code>class-account-validation.php<\/code> vraiment d\u00e9charg\u00e9e (chargement r\u00e9siduel dans <code>class-plugin.php<\/code> comment\u00e9)<\/li>\n<li>Restriction emails g\u00e9n\u00e9riques supprim\u00e9e dans <code>class-elementor-handler.php<\/code> \u2014 tous les emails cr\u00e9ent un compte<\/li>\n<li>Fallback <code>+tag<\/code> dans <code>class-magic-login.php<\/code><\/li>\n<li>Bouton inline \u00ab\u00a0\u00c9diter\u00a0\u00bb sous le nom supprim\u00e9 dans <code>shortcode-dashboard.php<\/code><\/li>\n<li><code>detect_organization()<\/code> et <code>consolidate()<\/code> d\u00e9sactiv\u00e9s \u2014 plus d&rsquo;auto-rattachement ni de fusion automatique de comptes<\/li>\n<\/ul>\n<h4>Nouvelles fonctionnalit\u00e9s (v3.2.0 \u2192 v3.2.1)<\/h4>\n<ul>\n<li>Onglet \u00ab\u00a0Mon organisation\u00a0\u00bb masqu\u00e9 quand aucune orga li\u00e9e<\/li>\n<li>Onglet RGPD toujours visible pour tous les utilisateurs (correction condition trop restrictive)<\/li>\n<li>Comptes de test exclus de la recherche contacts admin via meta <code>frnix_is_test_account<\/code><\/li>\n<li>Cap r\u00e9sultats recherche contacts port\u00e9 de 10 \u00e0 20<\/li>\n<\/ul>\n<h4>Corrections de donn\u00e9es<\/h4>\n<ul>\n<li><code>gmail.com<\/code> retir\u00e9 de <code>frnix_associated_domains<\/code> de Zayo Europe \u2014 5 users gmail d\u00e9tach\u00e9s<\/li>\n<li><code>outlook.com<\/code> (BoumIT) et <code>hotmail.co.uk<\/code> (HOTMAIL) nettoy\u00e9s \u2014 2 users d\u00e9tach\u00e9s<\/li>\n<li>Victoria Eppendahl (ID 2572) d\u00e9tach\u00e9e d&rsquo;ARAPEDE<\/li>\n<\/ul>\n<h4>Prochaines \u00e9tapes<\/h4>\n<ol>\n<li>R\u00e9percuter corrections v3.2.1 sur BIS<\/li>\n<li>Email one-shot contacts principaux<\/li>\n<li>Bug responsivit\u00e9 single page event<\/li>\n<li>Colonne \u00ab\u00a0Soci\u00e9t\u00e9 d\u00e9clar\u00e9e\u00a0\u00bb (frnix_company_name) dans tableau contacts admin<\/li>\n<\/ol>\n<\/details>\n<details open>\n<summary><strong>12 avril 2026 \u2014 Suppression workflow validation \u2014 cr\u00e9ation directe des comptes \u00e0 l&rsquo;inscription<\/strong><\/summary>\n<p><strong>Cat\u00e9gories :<\/strong> feature, workflow<\/p>\n<p><strong>Actions :<\/strong><\/p>\n<ul>\n<li><code>frnix-manager<\/code> v3.1.4 \u2192 v3.1.5<\/li>\n<li><code>class-elementor-handler.php<\/code> : suppression du branchement <code>needs_validation()<\/code> \/ <code>create_pending()<\/code> \u2014 tous les emails pro cr\u00e9ent d\u00e9sormais le compte WP directement sans passer par la file d&rsquo;attente<\/li>\n<li>Vidage manuel des 20 comptes pending et 2 comptes confirmed restants \u2192 validated via SQL (phpMyAdmin bis + Claude Code prod)<\/li>\n<li>Liste \u00ab\u00a0En attente\u00a0\u00bb vide sur bis et prod<\/li>\n<li>D\u00e9ploy\u00e9 sur bis puis prod + purge caches LiteSpeed + OPcache<\/li>\n<\/ul>\n<\/details>\n<details open>\n<summary><strong>12 avril 2026 \u2014 Refonte workflow inscriptions \u2014 suppression validation comptes + acceptation emails +tag<\/strong><\/summary>\n<p><strong>Cat\u00e9gories :<\/strong> feature, workflow<\/p>\n<p><strong>Actions :<\/strong><\/p>\n<ul>\n<li><code>frnix-manager<\/code> v3.1.3 \u2192 v3.1.4<\/li>\n<li>Suppression du cycle de validation des comptes (cron <code>frnix_check_pending_accounts<\/code> J+7\/J+30, suspension automatique)<\/li>\n<li>D\u00e9sactivation de <code>class-account-validation.php<\/code> (d\u00e9charg\u00e9e du plugin principal)<\/li>\n<li>Suppression du filtre <code>frnix_inscription_email<\/code> dans <code>class-email-consolidation.php<\/code> \u2014 les emails +tag@ sont d\u00e9sormais accept\u00e9s tels quels \u00e0 l&rsquo;inscription, sans conversion vers l&#8217;email principal<\/li>\n<li>Nettoyage automatique du cron au premier chargement post-mise \u00e0 jour (via version-flush)<\/li>\n<li>D\u00e9ploy\u00e9 sur BIS puis PROD<\/li>\n<\/ul>\n<\/details>\n<details open>\n<summary><strong>frnix-manager \u2014 10\/04\/2026 \u2014 Fix acc\u00e8s pages admin cach\u00e9es + lien fiche contact dashboard<\/strong><\/summary>\n<p><strong>Cat\u00e9gorie :<\/strong> bug-fix<\/p>\n<p><strong>Actions effectu\u00e9es :<\/strong><\/p>\n<ul>\n<li><strong>Bug 1 (reorder_menu)<\/strong> : les pages cach\u00e9es du sidebar (frnix-administration, frnix-account-validation, etc.) \u00e9taient exclues de <code>$submenu<\/code> lors du reorder \u2014 WordPress refusait l\u2019acc\u00e8s par URL directe. Fix : re-ajout des pages cach\u00e9es en fin de <code>$result<\/code> avant <code>$submenu['frnix-manager'] = $result<\/code>.<\/li>\n<li><strong>Bug 2 (dropdown quick search)<\/strong> : le lien contact pointait vers <code>frnix-administration&amp;search_contact=<\/code> au lieu de la fiche <code>\/mon-compte\/<\/code>. Corrig\u00e9 vers <code>home_url('\/mon-compte\/?admin_user_id=' . $user-&gt;ID . '&amp;nocache=1')<\/code> \u2014 <code>nocache=1<\/code> n\u00e9cessaire car LiteSpeed Cache servait la page sans ex\u00e9cuter le PHP.<\/li>\n<\/ul>\n<p><strong>Version :<\/strong> frnix-manager 3.1.3 (BIS + PROD)<\/p>\n<\/details>\n<details open>\n<summary><strong>frnix-manager \u2014 09\/04\/2026 (suite 3) \u2014 Tableaux Contacts + Organisations \u2014 fonctionnalit\u00e9s avanc\u00e9es<\/strong><\/summary>\n<p><strong>Fichiers modifi\u00e9s :<\/strong><\/p>\n<ul>\n<li><code>includes\/modules\/admin\/render-unified-tables.php<\/code> (60KB+)<\/li>\n<li><code>assets\/js\/pending-actions.js<\/code><\/li>\n<\/ul>\n<p><strong>Fonctionnalit\u00e9s livr\u00e9es :<\/strong><\/p>\n<ol>\n<li>Tableau Organisations : popover \u00ab\u00a0Nb contacts\u00a0\u00bb avec ronds color\u00e9s P\/F\/V\/B\/A + nom + email + cliquables<\/li>\n<li>Bouton \u00ab\u00a0\ud83d\udd0d Contacts\u00a0\u00bb par orga : modal recherche contacts similaires avec Levenshtein<\/li>\n<li>Modal contacts similaires : contacts d\u00e9j\u00e0 rattach\u00e9s + checkboxes P\/F\/V inline auto-save + Voir\/Masquer + ajout manuel + cr\u00e9ation nouveau contact<\/li>\n<li>Pastilles r\u00f4le par lettre (P\/F\/V\/B\/A\/?) avec couleurs<\/li>\n<li>Bouton changer cat\u00e9gorie orga inline (\u270f\ufe0f + select)<\/li>\n<li>Bouton Supprimer orga \u2192 frnix_org_hidden=1 + filtre \u00ab\u00a0Orgas supprim\u00e9es\u00a0\u00bb + Restaurer<\/li>\n<li>Compteur Nb contacts exclut contacts masqu\u00e9s<\/li>\n<li>Export CSV filtr\u00e9 \u00ab\u00a0Exporter la s\u00e9lection en CSV\u00a0\u00bb sur ligne filtres Contacts + Organisations<\/li>\n<li>Export s\u00e9lection group\u00e9e renomm\u00e9 \u00ab\u00a0Exporter la s\u00e9lection\u00a0\u00bb<\/li>\n<li>Contacts masqu\u00e9s exclus des recherches similaires et du popover Nb contacts<\/li>\n<li>Fiche orga d\u00e9di\u00e9e class-fiche-org.php cr\u00e9\u00e9e mais comment\u00e9e (bouton \u00c9diter \u2192 \/mon-compte\/?tab=organisation&amp;org_id=)<\/li>\n<\/ol>\n<\/details>\n<details open>\n<summary><strong>frnix-manager \u2014 09\/04\/2026 (suite) \u2014 Onglet \u00ab\u00a0En attente\u00a0\u00bb \u2014 fusion inscriptions + comptes WP, actions fonctionnelles<\/strong><\/summary>\n<p><strong>Fichiers modifi\u00e9s :<\/strong><\/p>\n<ul>\n<li><code>includes\/modules\/admin\/render-unified-tables.php<\/code> \u2014 <code>frnix_render_pending_view()<\/code> fusionn\u00e9e, <code>wp_enqueue_script<\/code> d\u00e9plac\u00e9 dans la fonction, handlers validate\/reject account<\/li>\n<li><code>assets\/js\/pending-actions.js<\/code> \u2014 handlers <code>frnix-p-validate-account<\/code> et <code>frnix-p-reject-account<\/code> ajout\u00e9s<\/li>\n<\/ul>\n<p><strong>Fonctionnalit\u00e9s livr\u00e9es :<\/strong><\/p>\n<ol>\n<li>Onglet \u00ab\u00a0En attente\u00a0\u00bb fusionne 2 sources : <code>wp_frnix_pending_registrations<\/code> (inscriptions) + comptes WP avec <code>frnix_account_status IN (pending\/confirmed)<\/code><\/li>\n<li>Badge Source : Inscription=orange \/ Compte=bleu<\/li>\n<li>Valider compte \u2192 <code>frnix_account_status=validated<\/code> \u2192 ligne dispara\u00eet du tableau<\/li>\n<li>Rejeter compte \u2192 <code>frnix_hidden=1<\/code> \u2192 ligne dispara\u00eet, visible dans filtre \u00ab\u00a0Emails masqu\u00e9s\u00a0\u00bb<\/li>\n<li>JS <code>pending-actions.js<\/code> charg\u00e9 via <code>wp_enqueue_script<\/code> dans <code>frnix_render_pending_view()<\/code> (<code>FRNIX_PLUGIN_URL<\/code>)<\/li>\n<li>Filtres mutuellement exclusifs r\u00f4le\/statut dans tableau Contacts<\/li>\n<li>Compteur Admins TBB : fusion WP administrators + <code>frnix_role_admin=1<\/code><\/li>\n<li>Samuel (ID2) + Amandine (ID351) + Philippe (ID348) : <code>frnix_organization_id=23761<\/code> + <code>frnix_role_admin=1<\/code> sur BIS<\/li>\n<\/ol>\n<\/details>\n<details open>\n<summary><strong>frnix-manager \u2014 09\/04\/2026 \u2014 Connexion TBB \u2192 tableaux unifi\u00e9s + filtres mutuellement exclusifs<\/strong><\/summary>\n<p><strong>Fichiers modifi\u00e9s :<\/strong><\/p>\n<ul>\n<li><code>includes\/modules\/admin\/class-admin-page.php<\/code> \u2014 liens TBB \u2192 frnix-contacts\/frnix-organisations, compteur Admins \u00e9tendu (WP + frnix_role_admin)<\/li>\n<li><code>includes\/modules\/admin\/render-unified-tables.php<\/code> \u2014 filtre role_filter=admin \u00e9tendu \u00e0 frnix_role_admin=1, filtres mutuellement exclusifs (role\/statut auto-reset)<\/li>\n<\/ul>\n<p><strong>Fonctionnalit\u00e9s livr\u00e9es :<\/strong><\/p>\n<ol>\n<li>Liens TBB cliquables \u2192 tableaux unifi\u00e9s : Admins\/Board\/Principaux\/Facturation\/Votants \u2192 <code>frnix-contacts&amp;role_filter=...<\/code> \/ Actifs\/Partenaires\/Individuels\/Non-membres \u2192 <code>frnix-organisations&amp;cat_filter=...<\/code><\/li>\n<li>Compteur Admins TBB : fusion WP administrators + <code>frnix_role_admin=1<\/code> (Samuel ID2, Amandine ID351, Philippe ID348 ajout\u00e9s)<\/li>\n<li>Filtre <code>role_filter=admin<\/code> dans tableau Contacts : d\u00e9tecte WP administrator OU <code>frnix_role_admin=1<\/code><\/li>\n<li>Filtres mutuellement exclusifs : changer r\u00f4le reset statut et vice versa, form auto-submit<\/li>\n<\/ol>\n<p><strong>Notes BIS :<\/strong><\/p>\n<ul>\n<li>Samuel (ID2), Amandine (ID351) : <code>frnix_organization_id=23761<\/code> + <code>frnix_role_admin=1<\/code> (\u00e0 r\u00e9pliquer sur PROD)<\/li>\n<li>Philippe Duby (ID348) : <code>frnix_role_board<\/code> vid\u00e9 + <code>frnix_role_admin=1<\/code> (\u00e0 r\u00e9pliquer sur PROD)<\/li>\n<\/ul>\n<\/details>\n<details open>\n<summary><strong>frnix-manager \u2014 08\/04\/2026 (suite 2) \u2014 Tableau Contacts unifi\u00e9 \u2014 En attente, filtres, tri, masquage<\/strong><\/summary>\n<p><strong>Fichiers modifi\u00e9s :<\/strong><\/p>\n<ul>\n<li><code>includes\/modules\/admin\/render-unified-tables.php<\/code> (43 134 octets) \u2014 tableau contacts complet<\/li>\n<li><code>assets\/js\/pending-actions.js<\/code> (4 511 octets) \u2014 handlers JS modals pending<\/li>\n<\/ul>\n<p><strong>Fonctionnalit\u00e9s livr\u00e9es :<\/strong><\/p>\n<ol>\n<li>Onglet \u00ab En attente \u00bb dans le tableau Contacts : fusion <code>wp_frnix_pending_registrations<\/code> (inscriptions) + comptes WP <code>frnix_account_status IN (pending\/confirmed)<\/code><\/li>\n<li>Badges Source : Inscription=orange \/ Compte=bleu<\/li>\n<li>Actions Inscription : Valider \/ Rattacher \/ Ignorer \/ Rejeter (handlers <code>frnix_pending_*<\/code>)<\/li>\n<li>Actions Compte : Valider \u2192 <code>frnix_account_status=validated<\/code> \/ Rejeter \u2192 <code>frnix_hidden=1<\/code> (masqu\u00e9)<\/li>\n<li>Colonnes triables : Date \/ Nom \/ Email \/ Organisation \/ Source \/ Statut (\u25b2\u25bc\u21c5)<\/li>\n<li>Filtre \u00ab Emails masqu\u00e9s \u00bb : affiche tous les contacts avec <code>frnix_hidden=1<\/code> (suspendus, rejet\u00e9s, masqu\u00e9s manuellement)<\/li>\n<li>Bouton \u00ab Supprimer \u00bb \u2192 masque (<code>frnix_hidden=1<\/code>), bouton \u00ab Restaurer \u00bb dans filtre masqu\u00e9s<\/li>\n<li>Filtre \u00ab Emails persos \u00bb : contacts avec domaine Gmail\/Hotmail\/Outlook\/etc<\/li>\n<li>Badge \u00ab Associ\u00e9 \u00bb : contacts avec <code>frnix_is_alias_of<\/code> non vide<\/li>\n<li>Bouton \u00ab Rattacher \u00e0 un contact \u00bb pour emails persos \/ \u00ab Rattacher \u00e0 une orga \u00bb pour emails pro<\/li>\n<li>JS <code>pending-actions.js<\/code> s\u00e9par\u00e9 (plus de heredoc PHP\u2192JS)<\/li>\n<\/ol>\n<p><strong>Notes :<\/strong><\/p>\n<ul>\n<li>Rejeter un compte = <code>frnix_hidden=1<\/code> (pas suspended) \u2014 comportement unifi\u00e9 avec bouton Supprimer<\/li>\n<li>Tableau Organisations : bouton \u00c9diter pointe vers <code>\/membres\/$slug<\/code> (page front)<\/li>\n<li>Crashes BIS \u00e9vit\u00e9s : <code>goto<\/code> supprim\u00e9, JS externalis\u00e9 en <code>.js<\/code> s\u00e9par\u00e9<\/li>\n<\/ul>\n<\/details>\n<details open>\n<summary><strong>frnix-manager \u2014 08\/04\/2026 (suite) \u2014 Tableaux unifi\u00e9s Contacts + Organisations \u2014 render-unified-tables.php<\/strong><\/summary>\n<p><strong>Fichiers cr\u00e9\u00e9s\/modifi\u00e9s :<\/strong><\/p>\n<ul>\n<li><code>includes\/modules\/admin\/render-unified-tables.php<\/code> (nouveau, ~28KB) \u2014 <code>frnix_render_contacts_unified()<\/code> + <code>frnix_render_organisations_unified()<\/code> + 6 handlers AJAX + JS inline<\/li>\n<li><code>includes\/modules\/admin\/class-admin-page.php<\/code> \u2014 <code>render_contacts_page()<\/code> remplac\u00e9 par appel unifi\u00e9, <code>render_organisations_page()<\/code> ajout\u00e9, submenu <code>frnix-organisations<\/code> enregistr\u00e9<\/li>\n<li><code>frnix-manager.php<\/code> \u2014 <code>require_once render-unified-tables.php<\/code> ajout\u00e9<\/li>\n<\/ul>\n<p><strong>Fonctionnalit\u00e9s livr\u00e9es :<\/strong><\/p>\n<ol>\n<li>Tableau Contacts unifi\u00e9 : colonnes \u2610\/Nom\/Email\/ORGANISATION\/R\u00d4LE(S)\/Statut\/Actions \u2014 992 contacts, pagination 50\/page<\/li>\n<li>Filtres : recherche texte + r\u00f4le + statut (Valid\u00e9\/En attente\/Confirm\u00e9\/Suspendu\/Contacts uniques\/Comptes persos) + bouton R\u00e9initialiser<\/li>\n<li>Badges r\u00f4les color\u00e9s : Principal=#0099FF, Votant=#FF9800, Facturation=#64CA8C, Board=#9C27B0, Admin=#888<\/li>\n<li>Actions par ligne : Voir (<code>\/mon-compte\/?admin_user_id=<\/code>) + Inviter + Rattacher (d\u00e9tection auto email perso\/pro)<\/li>\n<li>Rattacher email pro \u2192 modal autocomplete orga (<code>frnix_pending_search_org<\/code>)<\/li>\n<li>Rattacher email perso \u2192 modal autocomplete contact (<code>frnix_search_contact_for_alias<\/code>) + <code>frnix_set_alias<\/code><\/li>\n<li>Barre actions group\u00e9es : Demande de mise \u00e0 jour CONTACT + Exporter CSV avec page HTML interm\u00e9diaire<\/li>\n<li>Export CSV : page HTML avec textarea + bouton t\u00e9l\u00e9charger (s\u00e9parateur ; Excel FR)<\/li>\n<li>Comptes persos rattach\u00e9s (<code>frnix_is_alias_of<\/code>) masqu\u00e9s par d\u00e9faut, visibles via filtre Comptes persos<\/li>\n<li>Tableau Organisations unifi\u00e9 : colonnes \u2610\/Logo\/Nom\/Cat\u00e9gorie\/Contact principal\/Email principal\/Nb contacts\/Actions<\/li>\n<\/ol>\n<p><strong>Notes techniques :<\/strong><\/p>\n<ul>\n<li>Nonce dual : <code>frnix_pending_nonce<\/code> pour search org, <code>frnix_admin_nonce<\/code> pour les autres handlers<\/li>\n<li>Exclusion comptes test via <code>FRNIX_Test_Accounts::get_test_user_ids()<\/code><\/li>\n<li>Garde-fou BIS sur <code>frnix_bulk_invite<\/code> (<code>FRNIX_BIS_NO_EMAIL_USERS<\/code>)<\/li>\n<li><code>class-fiches.php<\/code> cr\u00e9\u00e9 puis supprim\u00e9 (approche abandonn\u00e9e au profit des tableaux)<\/li>\n<\/ul>\n<\/details>\n<p>nn<\/p>\n<details open>\n<summary><strong>frnix-manager \u2014 08\/04\/2026 \u2014 Module invitations \u2014 templates, UI 3 modes, anti-spam<\/strong><\/summary>\n<p><strong>Fichiers modifi\u00e9s :<\/strong><\/p>\n<ul>\n<li><code>includes\/class-invitation-email.php<\/code> (nouveau) \u2014 <code>FRNIX_Invitation_Email::send_invitation()<\/code><\/li>\n<li><code>includes\/class-frnix-email-template.php<\/code> \u2014 template <code>invitation_member<\/code> enregistr\u00e9 dans <code>init_templates()<\/code><\/li>\n<li><code>includes\/modules\/admin\/class-admin-page.php<\/code> \u2014 UI invitations 3 modes + 6 handlers AJAX<\/li>\n<li><code>includes\/class-gdpr-export.php<\/code> \u2014 fix double-wrap HTML (bypass <code>FRNIX_Email_Template::send()<\/code>, <code>wp_mail()<\/code> direct)<\/li>\n<li><code>wp-config.php<\/code> BIS \u2014 <code>define('FRNIX_BIS_NO_EMAIL_USERS', true)<\/code><\/li>\n<\/ul>\n<p><strong>Fonctionnalit\u00e9s livr\u00e9es :<\/strong><\/p>\n<ol>\n<li><strong>Fix rapport RGPD<\/strong> : HTML brut corrig\u00e9 \u2014 <code>generate_html_report()<\/code> bypasse <code>wrap()<\/code> via <code>wp_mail()<\/code> direct<\/li>\n<li><strong>Template invitation \u00e9ditable<\/strong> : slug <code>invitation_member<\/code>, variables <code>{{first_name}} {{last_name}} {{magic_url}} {{site_name}}<\/code>, visible dans <code>\/wp-admin\/admin.php?page=frnix-email-templates<\/code><\/li>\n<li><strong>Module invitations<\/strong> \u2014 panneau \u00ab\u00a0\ud83d\udce8 Envoi d&rsquo;invitations\u00a0\u00bb dans onglet Administration avec 3 modes :\n<ul>\n<li>Test sur moi : envoie \u00e0 current_user, pas de garde-fou BIS<\/li>\n<li>S\u00e9lection manuelle : autocomplete avec recherche SQL sur first_name\/last_name\/user_email, tags supprimables<\/li>\n<li>Par cat\u00e9gorie : 2 axes (cat\u00e9gorie orga \/ r\u00f4le contact), count en live<\/li>\n<\/ul>\n<\/li>\n<li><strong>Anti-spam<\/strong> : exclusion syst\u00e9matique des contacts avec <code>_last_login<\/code> \/ <code>wfls-last-login<\/code> \/ <code>frnix_last_modified<\/code> non vide<\/li>\n<li><strong>Garde-fou BIS<\/strong> : <code>FRNIX_BIS_NO_EMAIL_USERS<\/code> bloque les modes 2 et 3, UI bouton disabled + label \u00ab\u00a0Envoi d\u00e9sactiv\u00e9 (BIS)\u00a0\u00bb<\/li>\n<li><strong>Fix Comptes test<\/strong> : retir\u00e9 de <code>frnix_cleanup_submenus()<\/code> qui cassait l&rsquo;acc\u00e8s admin<\/li>\n<\/ol>\n<p><strong>Notes techniques :<\/strong><\/p>\n<ul>\n<li><code>frnix_account_status<\/code> filter : pending\/confirmed uniquement (validated\/active\/suspended exclus d\u00e9fensivement)<\/li>\n<li>Taxonomie <code>member_category<\/code> : nettoyage \u00e0 planifier (ELEM\/NL inutiles, doublons membre-actif\/membre-electeur\/membre-individuel)<\/li>\n<li>Cat\u00e9gories orga hardcod\u00e9es : <code>membre_actif<\/code> \/ <code>membre_partenaire<\/code> \/ <code>membre_individuel<\/code> \/ <code>non_membre<\/code> (post_meta <code>frnix_org_category<\/code>)<\/li>\n<\/ul>\n<\/details>\n<details open>\n<summary><strong>Session 08\/04\/2026 \u2014 Migration r\u00f4les multi-flags + nettoyage orgas\/contacts<\/strong> <span style=\"color:#888;\">[Feature, Refactor, Migration]<\/span><\/summary>\n<p><strong>Refactor mod\u00e8le r\u00f4les contacts :<\/strong><\/p>\n<ul>\n<li>Abandon de <code>frnix_contact_role<\/code> (single value) au profit de 4 metas binaires <code>frnix_role_principal\/votant\/facturation\/board<\/code> permettant le multi-r\u00f4les<\/li>\n<li>Migration des metas legacy <code>contact_organisation\/facturation\/votant<\/code> (string \u00ab\u00a0true\u00a0\u00bb) vers les nouveaux flags<\/li>\n<li>BIS : 475 principaux \/ 81 votants \/ 103 facturation \/ 8 board<\/li>\n<li>PROD : 451 principaux \/ 38 votants \/ 48 facturation \/ 8 board<\/li>\n<li>Nettoyage votants non-rattach\u00e9s \u00e0 une orga ACTIF (BIS: 381 \/ PROD: 376 supprim\u00e9s)<\/li>\n<li>Nettoyage facturation rattach\u00e9s \u00e0 des non-membres<\/li>\n<li>Auto-marquage des single-contact orgas (actif\/partenaire\/individuel\/non-membre)<\/li>\n<\/ul>\n<p><strong>Dashboard FRNIX patch\u00e9 :<\/strong><\/p>\n<ul>\n<li><code>$user_counts<\/code> bascul\u00e9 sur <code>frnix_role_*<\/code> au lieu des metas legacy<\/li>\n<li>Compteur \u00ab\u00a0Contacts\u00a0\u00bb filtr\u00e9 sur frnix_member + frnix_contact (au lieu de tous les wp_users)<\/li>\n<li>Tuile \u00ab\u00a0Nouveaux (30j)\u00a0\u00bb supprim\u00e9e \u2014 grille pass\u00e9e \u00e0 3 colonnes<\/li>\n<li><code>frnix_org_category<\/code> peupl\u00e9 sur les 579 orgas PROD via <code>frnix_get_organization_type()<\/code><\/li>\n<li>Cases <code>admins<\/code> et <code>board<\/code> dans les filtres dashboard alig\u00e9s sur le nouveau mod\u00e8le<\/li>\n<\/ul>\n<p><strong>Cr\u00e9ation\/migration utilisateurs :<\/strong><\/p>\n<ul>\n<li>3 admins cr\u00e9\u00e9s sur BIS avec IDs PROD via SQL direct (Striolet 2, Estrade 351, Duby 348)<\/li>\n<li>25 contacts facturation cr\u00e9\u00e9s sur PROD depuis <code>email_de_facturation<\/code> des orgas actives<\/li>\n<li>13+19 contacts cr\u00e9\u00e9s via script externe (PROD\/BIS) pour FOLIATEAM, I3D.NET, KYXAR, NETALIS, RETELIT, KYXAR, POST LUX, VERISIGN, WORLDLINE\u2026<\/li>\n<li>HUB ONE : email avec point-virgule sanitis\u00e9 incorrectement par WP \u2014 corrig\u00e9 manuellement via SQL<\/li>\n<\/ul>\n<p><strong>Fusion FAIR :<\/strong><\/p>\n<ul>\n<li>5 doublons FAIR fusionn\u00e9s vers FAIR Conseil et Services (25818) sur BIS et PROD<\/li>\n<li>FAIR Conseil bascul\u00e9 en actif, Rapha\u00ebl Boukris (2820) rattach\u00e9 comme principal\/facturation\/votant<\/li>\n<\/ul>\n<p><strong>UI dashboard mon-compte :<\/strong><\/p>\n<ul>\n<li>Bouton \u00ab\u00a0\u00c9diter\u00a0\u00bb inop\u00e9rant corrig\u00e9 : <code>frnixSetMode(window.frnixEditMode || 'admin')<\/code><\/li>\n<li>Bandeau preview activ\u00e9 pour les admins (<code>$show_banners=true<\/code>) avec retrait CSS de <code>frnix-preview-mode<\/code><\/li>\n<li>R\u00e8gle CSS <code>.frnix-preview-mode .frnix-banner { display:none }<\/code> comment\u00e9e<\/li>\n<\/ul>\n<p><strong>Maintenance CSS :<\/strong><\/p>\n<ul>\n<li>Mu-plugin <code>frnix-header-css-fix.php<\/code> : regen complet (page\/post\/jet-engine) sur init si critique manquant + clear_cache hook<\/li>\n<li>Cron horaire <code>frnix_css_regen<\/code> ajout\u00e9 sur BIS et PROD<\/li>\n<li>Carte \u00ab\u00a0Maintenance CSS\u00a0\u00bb + AJAX <code>frnix_regen_css<\/code> dans onglet Outils<\/li>\n<\/ul>\n<p><strong>TODO :<\/strong><\/p>\n<ul>\n<li>FrnixCore_EmailManager (toujours en attente)<\/li>\n<li>57 orgas actives sans contact (export CSV dispo : <code>uploads\/orgas-sans-contact.csv<\/code>)<\/li>\n<li>Tuile \u00ab\u00a0Membres\u00a0\u00bb du dashboard compte des organisations, pas des users \u2014 \u00e0 clarifier<\/li>\n<\/ul>\n<\/details>\n<details open>\n<summary><strong>Session 07\/04\/2026 \u2014 Templates emails + migration PROD v3.0.8<\/strong> <span style=\"color:#888;\">[Feature, Deploy, UI]<\/span><\/summary>\n<p><strong>Feature :<\/strong><\/p>\n<ul>\n<li><code>class-email-templates.php<\/code> : \u00e9diteur TinyMCE (Visuel), suppression tabs HTML\/Aper\u00e7u, generate_preview() lit les overrides, bouton \u00c9diter ouvre en Aper\u00e7u, bouton Aper\u00e7u ouvre version sauvegard\u00e9e dans nouvel onglet<\/li>\n<li><code>class-unsubscribe.php<\/code> : nouveau module, token s\u00e9curis\u00e9 bin2hex\/sha256, page \/desinscription\/, suspension compte, footer email avec lien \u00ab\u00a0Se d\u00e9sinscrire\u00a0\u00bb (conditionnel user_id)<\/li>\n<li>1019 comptes existants migr\u00e9s en statut \u00ab\u00a0validated\u00a0\u00bb<\/li>\n<li>Menu admin nettoy\u00e9 (frnix_cleanup_submenus) sur BIS et PROD<\/li>\n<li>CSS JetEngine ID 14878 ajout\u00e9 au mu-plugin frnix-header-css-fix.php<\/li>\n<\/ul>\n<p><strong>Deploy :<\/strong><\/p>\n<ul>\n<li>Migration PROD compl\u00e8te : 7 modules v3.0.8 + 9 fichiers sync BIS\u2192PROD<\/li>\n<li>Table <code>wp_frnix_unsubscribe_tokens<\/code> cr\u00e9\u00e9e sur BIS et PROD<\/li>\n<li>Page \/desinscription\/ cr\u00e9\u00e9e sur BIS (ID 26205) et PROD (ID 26189)<\/li>\n<\/ul>\n<p><strong>TODO :<\/strong><\/p>\n<ul>\n<li>FrnixCore_EmailManager pour centraliser wp_mail() avec user_id<\/li>\n<li>Nettoyage emails : +tag, restructuration 3 champs, suppression alias<\/li>\n<li>Navigation admin style Apple avec sous-onglets conditionnels<\/li>\n<\/ul>\n<\/details>\n\n","protected":false},"excerpt":{"rendered":"<p>&#128221; v3.5.25-alpha &mdash; Help text wizard contact : champ organisation &#9989; Fix class-wizard-schema.php &mdash; champ frnix_organization_id : help text remplac&eacute; par &laquo;&nbsp;Recherchez votre organisation, ou laissez vide.&nbsp;&raquo;. Bump frnix-manager v3.5.24-alpha &rarr; v3.5.25-alpha (header + define FRNIX_VERSION) Bump FRNIX_Wizard::VERSION = &#39;3.5.25-alpha&#39; &#129534; Justification Ancien help text invitait &agrave; cocher frnix_is_individuel, mais ce champ est verrouill&eacute; admin-only [&hellip;]<\/p>\n","protected":false},"author":26,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"hf_cat_page":[],"class_list":["post-26165","page","type-page","status-publish","hentry"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/frnix.org\/de\/wp-json\/wp\/v2\/pages\/26165","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/frnix.org\/de\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/frnix.org\/de\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/frnix.org\/de\/wp-json\/wp\/v2\/users\/26"}],"replies":[{"embeddable":true,"href":"https:\/\/frnix.org\/de\/wp-json\/wp\/v2\/comments?post=26165"}],"version-history":[{"count":5,"href":"https:\/\/frnix.org\/de\/wp-json\/wp\/v2\/pages\/26165\/revisions"}],"predecessor-version":[{"id":26729,"href":"https:\/\/frnix.org\/de\/wp-json\/wp\/v2\/pages\/26165\/revisions\/26729"}],"wp:attachment":[{"href":"https:\/\/frnix.org\/de\/wp-json\/wp\/v2\/media?parent=26165"}],"wp:term":[{"taxonomy":"hf_cat_page","embeddable":true,"href":"https:\/\/frnix.org\/de\/wp-json\/wp\/v2\/hf_cat_page?post=26165"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}