Commit Graph

992 Commits

Author SHA1 Message Date
Colin Maudry e763a0b878 Taille du point de l'org 2026-07-03 22:29:04 +02:00
Colin Maudry 86977bd37e fix(figures): rendre le point de l'organisme en icône plutôt qu'en circleMarker
bringToFront() sur un circleMarker SVG (overlayPane) ne pouvait pas passer
devant les bulles de cluster (markerPane, toujours au-dessus dans l'ordre
des panes Leaflet), et le rendu SVG se redimensionnait visuellement pendant
l'animation de zoom. Le point is_home est maintenant un L.marker + divIcon
(comme les clusters), avec zIndexOffset élevé : toujours au premier plan et
taille constante quel que soit le zoom.
2026-07-03 22:17:54 +02:00
Colin Maudry f1c28acc96 feat(figures): mettre en avant le point de l'organisme consulté sur la carte
Marque is_home=True sur les marqueurs du home_type (acheteur ou titulaire
selon la page) dans get_org_location_map. Côté client, pointToLayer donne
à ce point un rayon légèrement plus grand (8 vs 5) et le ramène toujours
au premier plan (bringToFront), indépendamment de l'ordre des couches.
2026-07-03 22:08:43 +02:00
Colin Maudry a96f772d7a fix(figures): désactiver l'animation du fitBounds sur les cartes organisme
Un fitBounds animé interrompu (deux Input sur pathname+année pouvant
re-déclencher le callback quasi simultanément) laissait le transform CSS
de zoom de Leaflet figé à une grande échelle (ex: scale(16)), faisant
apparaître les marqueurs individuels démesurément gros sur /acheteurs et
/titulaires. Constaté en vérification manuelle sur test.colibre.fr.
2026-07-03 16:43:04 +02:00
Colin Maudry 22dd49f337 docs(figures): corriger le commentaire d'ordre des couches GeoJSON
Le commentaire affirmait à tort que l'organisme consulté est toujours
peint au-dessus de sa contrepartie ; l'ordre est en réalité fixe
(titulaire puis acheteur), indépendant de home_type. Relevé par la
revue finale de branche.
2026-07-03 16:15:13 +02:00
Colin Maudry acb8d5e0d1 feat(titulaire): afficher les acheteurs sur la carte de la fiche titulaire
Supprime point_on_map, devenue inutilisée après migration des deux pages
vers get_org_location_map.
2026-07-03 16:10:02 +02:00
Colin Maudry d201b7a3c6 feat(acheteur): afficher les titulaires sur la carte de la fiche acheteur 2026-07-03 16:05:05 +02:00
Colin Maudry 8b69fee31c feat(figures): ajouter get_org_location_map (carte cluster organisme + contrepartie) 2026-07-03 15:59:47 +02:00
Colin Maudry 21d3a30d8b refactor(figures): extraite build_org_markers pour réutilisation 2026-07-03 15:55:29 +02:00
Colin Maudry ad872d3b2c docs: ajouter le plan d'implémentation des cartes acheteur/titulaire 2026-07-03 15:48:32 +02:00
Colin Maudry f301c2ab0f docs: ajouter le design des cartes acheteur/titulaire avec contrepartie 2026-07-03 15:15:46 +02:00
Colin Maudry caf800e5e8 fix(admin): guard find_changed_cell against cross-table schema mismatch
When switching tables, the table-switch branch writes fresh data for the
new table, which re-fires the same callback with data_previous still
holding the old table's rows. find_changed_cell only checked row count
before diffing, so if the two tables happened to have the same number of
rows it would zip mismatched-schema dicts and report a spurious changed
cell (usually the PK column), producing a confusing red alert right after
switching tables.
2026-07-03 14:46:12 +02:00
Colin Maudry d229b58f3b feat(admin): replace dedicated pages with a generic table editor at /admin 2026-07-03 14:19:01 +02:00
Colin Maudry cf23863a30 refactor(admin): apply formatting fixes from linter hooks 2026-07-03 13:04:15 +02:00
Colin Maudry 19991dd22f Ajouter le plan d'implémentation de l'éditeur générique de tables (/admin) 2026-07-03 12:34:22 +02:00
Colin Maudry 6bec76535c Remplacer le design du panneau admin par un éditeur générique de tables
Pivot avant merge : au lieu de pages dédiées par cas d'usage, une seule
page /admin avec sélecteur de table + édition de cellule DataTable,
plus facile à faire évoluer au fil des besoins de support.
2026-07-03 12:27:04 +02:00
Colin Maudry cfcbfe9768 Ajouter la colonne handle Frisbii à l'historique d'abonnements (admin) 2026-07-03 11:55:51 +02:00
Colin Maudry 8eb5c06198 Changelog v3.0.0 2026-07-03 11:44:59 +02:00
Colin Maudry 43122a7c12 Rédactionnel dans la page d'abonnements 2026-07-03 11:43:41 +02:00
Colin Maudry 348da79175 test(admin): verify login succeeded in non-admin 404 test
test_admin_non_admin_gets_404 asserted the same /admin 404 that
anonymous visitors also get, without first confirming the login
actually went through. A broken login (falls back to /connexion on
bad credentials, unverified email, etc.) would leave the session
anonymous and the test would keep passing for the wrong reason,
silently degrading into a duplicate of test_admin_anonymous_gets_404.
Now waits for the post-login redirect to /compte/abonnement (this
user has no subscription) before exercising the admin guard.
2026-07-03 10:44:31 +02:00
Colin Maudry 7cc1fadf0f test(admin): add end-to-end Selenium coverage for the admin panel
Covers anonymous → 404, non-admin → 404, and the full admin flow
(list, detail, status change, journal) through a real login and a
real running app. tests/users.test.sqlite is committed and shared by
the whole Selenium session, so the test cleanup also resets the
sqlite_sequence high-water marks that plain DELETEs don't roll back,
keeping the file byte-stable across runs. This run additionally bakes
in migration 0006_create_admin_actions (new admin_actions table), the
first time any Selenium test has booted the real app since that
migration was added — the same one-time process by which migrations
0001-0005 already ended up committed in this fixture.
2026-07-03 10:34:35 +02:00
Colin Maudry 5d56f8180a feat(admin): add /admin/journal audit log page 2026-07-03 10:24:40 +02:00
Colin Maudry f8d1e60519 feat(admin): add /admin/user/<user_id> detail page 2026-07-03 10:20:17 +02:00
Colin Maudry 96358423df feat(admin): add /admin user list page 2026-07-03 10:13:04 +02:00
Colin Maudry e483d7af4d feat(admin): add subscription-status mutation route
Wires is_admin(), SUBSCRIPTION_STATUSES/get_current/set_status, and
log_action() into POST /admin/actions/subscription-status: validates
the requested status and that subscription_id matches the user's
current subscription, applies the change, and logs an audit entry.
Registers the admin blueprint in init_auth() and documents ADMIN_EMAIL
in .template.env.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 09:46:22 +02:00
Colin Maudry 2f2cd151fb feat(admin): add is_admin() access guard
Implement access control function for admin panel. Returns True only if
ADMIN_EMAIL env var is set, user is authenticated, and email matches
case-insensitively.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 09:41:57 +02:00
Colin Maudry c4851ff0ae refactor: format test_db.py for consistency
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 09:38:46 +02:00
Colin Maudry fb62c28e10 feat(admin): add admin_actions audit table and log/list functions
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 09:38:33 +02:00
Colin Maudry 0209ec0d5c feat(admin): add subscription history, status override, and statuses constant
Adds four new DB helpers for the admin panel:
- SUBSCRIPTION_STATUSES: tuple of valid subscription statuses
- list_by_user(): retrieve all subscriptions for a user (newest first)
- set_status(): override a subscription's status and updated_at timestamp
- get_subscriber_state(): public wrapper for internal _get_state()

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 09:34:09 +02:00
Colin Maudry 9ea8bee940 feat(admin): add list_users() to auth DB layer
Implements list_users(limit: int = 1000) -> list[sqlite3.Row] in the auth
DB layer to retrieve all users ordered by creation date (most recent first).

- Returns all users, optionally capped at limit (default 1000)
- Orders by created_at DESC to show newest users first
- Follows existing DB layer patterns using get_conn().execute().fetchall()

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-03 09:29:03 +02:00
Colin Maudry e820041cef Ajouter le plan d'implémentation du panneau admin (/admin) 2026-07-03 09:19:15 +02:00
Colin Maudry e678399fe7 Préciser la pagination native (20/page) du tableau /admin 2026-07-03 09:07:27 +02:00
Colin Maudry 2cbee97afb Ajouter le spec du panneau admin interne (/admin)
Design pour un panneau de support/débug (liste des comptes, historique
d'abonnements, correction manuelle de statut) protégé par ADMIN_EMAIL,
avec journal d'audit en base plutôt qu'en logs applicatifs.
2026-07-03 09:02:14 +02:00
Colin Maudry 0b88a65414 Utiliser le Checkout API pour la session de souscription (accept_url/cancel_url)
hosted_page_links.payment_info (POST /v1/subscription) n'honore pas
accept_url/cancel_url malgré la doc, même passés en query string (constaté
en test sur test.colibre.fr). On génère maintenant la page de paiement via
POST /v1/session/subscription (Checkout API), qui accepte ces champs dans
son body et redirige effectivement le navigateur — même mécanisme déjà
fonctionnel pour l'ajout de moyen de paiement (create_recurring_session).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-02 18:21:05 +02:00
Colin Maudry 14ae1a7bfb Gérer l'affichage d'un abonnement expiré (statut Frisbii "expired")
_show_active_view affichait par erreur la vue "abonnement actif" (avec un
faux "Prochaine facturation") pour un abonnement expiré. Un abonnement
expiré bascule maintenant sur l'écran de re-souscription, avec une alerte
dédiée. Jamais remarqué jusqu'ici car les webhooks Frisbii ne remontaient
pas ce changement de statut.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-02 18:13:12 +02:00
Colin Maudry 1159697c0e Fix redirection Frisbii après ajout de moyen de paiement au premier abonnement
accept_url/cancel_url n'existent pas dans le schéma de POST /v1/subscription
(ils y sont silencieusement ignorés) : Frisbii attend ces paramètres en
query string sur le lien hosted_page_links.payment_info retourné. Ajout
d'un warning loggé sur signature de webhook invalide, jusque-là silencieuse.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-02 17:56:19 +02:00
Colin Maudry ea20491e9c Changements rédactionnels : abonnement par virement, avantage abonnements 2026-07-02 16:50:33 +02:00
Colin Maudry 8a428ac1aa Ajout d'une conf de redirection nginx de test 2026-07-02 16:49:03 +02:00
Colin Maudry d08f7aeeac Nombre de jours d'essai en dur plutot que via appels HTTP 2026-07-02 13:55:22 +02:00
Colin Maudry 1bdcaaf5d8 Réactivation de l'env MAIL_SUPPRESS_SEND 2026-07-02 13:42:05 +02:00
Colin Maudry a38b2d5e71 Remplacement du Loading... screen 2026-07-02 12:03:50 +02:00
Colin Maudry 74afb7aef8 Nettoayge 2026-07-02 11:46:42 +02:00
Colin Maudry 2ed560d4e8 Nettoayge 2026-07-02 11:32:45 +02:00
Colin Maudry cd107a0213 Refactor structure modules pages/compte, petits changements de texte 2026-07-02 10:53:01 +02:00
Colin Maudry 9ff2373ccb decp.info => colibre 2026-07-01 18:00:36 +02:00
Colin Maudry 126834c7d4 fix(subscriptions): un abonnement en échec (failed) ne bloque plus le réabonnement 2026-07-01 16:56:34 +02:00
Colin Maudry 872fc33dd7 feat(subscriptions): cancel/webhook/add_payment_callback sur get_current et customer_known 2026-07-01 16:41:57 +02:00
Colin Maudry 0ffe647657 feat(subscriptions): subscribe() génère et transmet le handle, mark_failed en cas d'échec 2026-07-01 14:37:25 +02:00
Colin Maudry 179e6e436d feat(subscriptions): create_subscription_session prend le handle en paramètre 2026-07-01 14:34:09 +02:00
Colin Maudry 64158e9080 feat(subscriptions): historique multi-lignes + subscriber_state + handle abo-{user_id}-N
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-01 14:29:47 +02:00