Commit Graph
24 Commits
Author SHA1 Message Date
Claude af5933b5a7 Lot 6 : Grille plus légère, Commandes allégées et nettoyage
- Grille : réglages écrits dans le localStorage au plus toutes les 500 ms
  (immédiatement à la fermeture), tendance réseau et texte de recherche
  calculés une fois par ligne, courbe de tendance mémorisée, barre du bas
  abonnée au seul nombre de modifications.
- Commandes : appels « franco » 6 par 6 ; dernière réception limitée aux
  fournisseurs du cadencier (résultats identiques sur la base de test).
- Dépendances inutilisées retirées (react-query, @google/genai, ai,
  react-markdown, remark-gfm, xlsx, @radix-ui/react-dropdown-menu) ;
  pnpm-lock.yaml supprimé (npm est utilisé par Docker et le README).
- Code mort et journaux de build retirés.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AcA129WzGTH6zxPHFBGWmn
2026-10-04 06:48:43 +00:00
Claude 7da4c6d5fd perf: lot 1 — chargements plus rapides et corrections, sans changement visuel
Grille (navigateur)
- « Rafraîchir » ne passe plus par l'URL : le paramètre _refresh restait
  mémorisé et chaque retour par le menu forçait un recalcul serveur complet
  (migration du store pour nettoyer les valeurs déjà enregistrées).
- Lignes reçues regroupées toutes les 300 ms au lieu de reconstruire tout le
  tableau à chaque paquet de 150 (chargement quadratique).
- Sélection indexée par code article (getRowId) : après un filtre, l'action
  groupée visait d'autres produits. Seules les lignes affichées comptent.
- Recherche : un passage par ligne au lieu d'un par colonne ; formateurs de
  nombres partagés (lib/format.ts) ; colonnes mensuelles mémorisées ;
  plus de transition-all sur les lignes positionnées par transform.
- exceljs, jspdf et xlsx chargés au clic seulement.

Grille (serveur)
- Requêtes Qlik et snapshot lancées en parallèle de la phase SQL.
- Cache mémoire borné (LRU) ; calcul en cours réutilisé même en forcé ;
  flux interrompu quand le client part.
- Après un enregistrement, les gammes sont reportées dans le cache et dans
  grid_rows au lieu d'invalider (recalcul de ~40 s évité).

Données et API
- lib/ff-cache.ts : cache mémoire 30 min des lectures FF (stock, hit-parade,
  CA mensuel, fournisseurs, dernière réception, publicités), vidé en fin de
  synchro nocturne ; erreurs jamais gardées.
- Pool PostgreSQL unique (globalThis), réglage sans workers parallèles posé
  une fois par connexion au lieu d'une transaction autour de chaque requête.
- Délai maximal sur tous les appels à l'API FF.
- Index session_snapshots ; commandes : plus de double rechargement ;
  synchro : saisies regroupées ; paramètres : configuration lue une fois ;
  journal de capture en ajout seul, rien de formaté sans capture ouverte.

Corrections
- Historique : l'échec de chargement s'affiche (au lieu de « Aucun snapshot »).
- Sessions et validations enregistrent le magasin affiché, plus « TOTAL ».
- Publicités : libellé du statut « passées ».

Plan complet : docs/plan-optimisation-webui.md

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AcA129WzGTH6zxPHFBGWmn
2026-10-03 20:28:14 +00:00
Claude 94e82aa404 fix(ff): le panneau API FF Nancy affichait une coquille vide + URL configurable
Deux problèmes distincts, dont un mal diagnostiqué au départ.

1. FORMAT DE RÉPONSE — cause réelle du « test ne donne rien ». Le serveur
   fonctionne (vérifié : HTTP 200, synchro du jour, 33 tables), mais il renvoie
   { sync: [{ table_name, last_sync, rows_synced, status, error_msg }] } alors
   que l'application lisait { lastSync, tables: [{ nom, derniereSync, nbLignes }] }.
   Les champs n'existaient pas : le panneau s'affichait vide sans erreur, la
   requête HTTP ayant réussi. normalizeSyncStatus() traduit désormais les deux
   formes, et le tableau expose l'état par table (une table en erreur est
   justement l'information qu'on vient chercher).

2. URL NON CONFIGURABLE. FF_API_BASE était figée au chargement du module depuis
   process.env, sans champ dans l'interface : impossible de corriger l'adresse
   sans redéployer. Elle est maintenant résolue à l'appel — réglage enregistré,
   puis variable d'environnement, puis défaut — avec un champ, un bouton
   Enregistrer et un test dans Paramètres.

Le test distingue désormais DNS, connexion refusée, délai dépassé et code HTTP,
et affiche l'adresse réellement appelée : un « HTTP 503 » nu ne permettait pas
de séparer une mauvaise URL d'une panne. /api/ff-status renvoie le même détail.

Ajout au passage du paramètre `compute` dans la doc API des Paramètres.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y26nRZxTR57K7h8yqsF675
2026-08-06 10:56:29 +00:00
MichaelandClaude Opus 4.8 aee968d30f feat(grid): replace ranking/AI/score with Qlik network data
Remove ranking, AI analysis (routes + ai-copilot module), and score-engine
from the grid. Add Qlik Sense network metrics (CA, Qte, nb magasins per
product) joined by code centrale (articles.artcentrale).

- qlik-client.ts: NTLM + ticket SSO auth, QIX hypercube extraction (master items)
- qlik-network-cache.ts + qlik_network_metrics table (db-init): cache layer
- POST /api/qlik/sync?fournisseur=: per-supplier sync into cache
- SyncQlikButton: per-supplier sync, grid reload, last-update date display
- get-product-rows Phase 8: enrich rows with cached network metrics
- heatmap-grid: CA reseau / Qte reseau / Magasins (/270) / % presence columns
- discovery: app 9872ee6e, master items CA N / Quantite N / Magasin Ventes Nb N
- deps: httpntlm, ws

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-20 22:52:39 +02:00
Michael df1d059952 feat: implement API clients for Nancy FF data sync and add local configuration settings 2026-04-24 10:43:32 +02:00
Michael a06d7cd7e8 feat: create API client for FF Nancy REST API to synchronize supplier, article, and movement data 2026-04-24 10:22:05 +02:00
Michael c63a60c0cf feat: implement PostgreSQL client for FF Nancy API data with bulk SQL queries, replacing per-article HTTP calls. 2026-03-23 11:58:50 +01:00
MichaelandClaude Sonnet 4.6 65f455b4e2 perf: referentiel+ranking only for articles with sales, per-article ranking
The ranking bulk endpoint is capped at 500 by the API server, making
it useless for full supplier matching. Per-article ranking (codein filter)
works correctly and is now called only for articles WITH sales data.

getProductRows restructured:
- Phase 2A: mensuel + commandes in parallel (all articles)
- Phase 2B: referentiel + ranking in parallel, only for articlesWithData
  (articles that appear in mensuelMap)

For a 45060-article supplier with 5446 with sales:
- Referentiel: 45060 → 5446 calls (88% reduction)
- Ranking: 45060 → 5446 calls (88% reduction)

totalRankedProducts fetched from GET /api/ranking?limit=500 count.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 22:02:12 +01:00
MichaelandClaude Sonnet 4.6 383b8ccac7 fix: ranking bulk match by codein AND gencod/gtin, add entry key logging
The bulk ranking response (GET /api/ranking?limit=30000) may use
'gencod' instead of 'codein' as the article identifier. Added:
- gtin→codein lookup map built from article gtin fields
- Match entries by entry.codein first, then by entry.gencod→article.gtin
- Diagnostic logging of the first entry's keys and values to identify
  the correct identifier field in the API response
- Increased fallback per-article batchSize from 20 to 50

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 21:51:42 +01:00
MichaelandClaude Sonnet 4.6 1cd3ade77e perf: remove actif filter, increase batchSize, exclude Y articles without sales
- Remove actif/suspendu filter that caused wrong stats (893€ CA, 249 units)
  by incorrectly excluding products with sales. The parallel pagination
  and bulk ranking fixes are sufficient to handle large suppliers.
- Increase getMensuelByArticles and getReferentielByArticles batchSize
  from 20 to 50, reducing sequential batch iterations by ~2.5x.
- Filter gamme Y products with zero 12-month sales from returned rows.
  Reduces grid size (e.g. S053: 14775→fewer rows) without affecting
  products that actually sold. Y products with sales are preserved.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 21:23:34 +01:00
MichaelandClaude Sonnet 4.6 be3a196744 perf: parallel article pagination + single-call full ranking fetch
Article pagination:
- fetchAllPages fallback now fetches 10 pages in parallel instead of
  sequentially. Stops as soon as any page returns < pageSize items.
  For S053 (30 pages), reduces sequential time by ~10x.

Ranking:
- getRankingByArticles now fetches the entire network ranking in one
  call (GET /api/ranking?limit=30000) and matches by codein.
  Replaces foucentrale bulk (which returned 0) and per-article fallback
  (which would be 8889 calls for S053).
- totalRankedProducts = actual number of entries returned by the API.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 20:58:03 +01:00
Michael 69c7d65482 feat: Add Claude settings to allow specific Git and Next.js Bash commands. 2026-03-19 20:06:11 +01:00
MichaelandClaude Sonnet 4.6 dcebf74f31 perf: replace N ranking API calls with 1 bulk fetch per supplier
getRankingByArticles now uses GET /api/ranking?foucentrale=<code>
to fetch all rankings for a supplier in a single request instead of
making one request per article. For a 500-article supplier this goes
from ~500 HTTP calls to 2 (count + bulk), eliminating the timeout
that caused the client-side crash on large suppliers.

Falls back to per-article requests if no codeFournisseur is provided
or if the bulk endpoint fails.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 18:53:49 +01:00
Michael aa69637f98 feat: Introduce bulk AI analyzer component to pre-classify products and prepare data for AI analysis, including context profiling. 2026-03-19 13:19:49 +01:00
Michael 34529f3934 feat: add FF Nancy API client for fetching suppliers, articles, and movements with pagination and data mapping. 2026-03-19 12:55:55 +01:00
Michael 8b7d81b20c feat: implement product grid with comprehensive product data fetching, processing, and heatmap display. 2026-03-19 12:41:03 +01:00
Michael c303427dd0 feat: implement a centralized HTTP client for the FF Nancy REST API, including data types, pagination, and functions for suppliers, articles, and movements. 2026-03-18 20:00:45 +01:00
MichaelandClaude Sonnet 4.6 8986f7d001 feat: integrate /referentiel endpoint for nomenclature, gamme, stock, PA
Replaces ventesProduits DB query with API call to /articles/:no_id/referentiel.
Called in parallel with mensuel and commandes.

Extracts:
- article.nom_code/nom_libelle → code3/libelle3 (nomenclature)
- gammes[0].gamme_code → codeGamme + codeGammeInit (frozen initial)
- prix.achat + fournisseurs[0].pcb → pa/prixAchat/pcb
- stock[] → stockActuel/stockTotal/stockValeur (real-time)
- performance.derniere_vente/derniere_entree → derniereVente/derniereLivraison

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 19:26:47 +01:00
MichaelandClaude Sonnet 4.6 47e617afd3 feat: restore reference, gtin, gamme initiale and nomenclature
api-ff-client.ts:
- FfArticle: add reference (ref_fou_principale) and gtin fields
- getArticlesByFournisseur: map ref_fou_principale → reference, gtin → gtin

get-product-rows.ts:
- ProductRow seeded with reference and gtin from API articles
- Phase 6: read codeGamme, codeGammeInit, code3, libelle3 from ventesProduits
  (read-only, DISTINCT ON codein ordered by updated_at DESC)
- Phase 7 snapshot still overrides DB gammes when a snapshot exists

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 18:08:21 +01:00
MichaelandClaude Sonnet 4.6 58f17152a1 feat: switch to /articles/:no_id/mensuel endpoint for sales & stock data
Replaces bulk mouvements pagination + per-article stock N+1 with a single
batched call to the new mensuel endpoint (confirmed working via diag).

api-ff-client.ts:
- Remove getStockByFournisseur (no longer needed)
- Add FfMensuelEntry/Ventes/Receptions interfaces
- Add getMensuelByArticles(articles, dateDebut, dateFin, batchSize=20)
  → Map<codein, FfMensuelEntry[]> using no_id as API identifier

get-product-rows.ts:
- Phase 2: getMensuelByArticles + getCommandesByFournisseur in parallel
- Phase 5: aggregate mois×site entries → sales12m, stock12m, workingStores
  - qte_vendue / ca_ht are negative → Math.abs()
  - stock carry-forward for months with no data
  - pa from prmp_fin_mois

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 18:00:55 +01:00
MichaelandClaude Sonnet 4.6 5c40a615c7 fix: correct API field names for articles and mouvements endpoints
Articles:
- noid: r.no_id (was r.noid)
- codefou: r.codefou_principal (was r.codefou)
- nomfou: r.nom_fou_principal (was r.nomfou)
- pcb: r.pcb_principal (was r.pcb)

Mouvements:
- datemvt: r.datmvt (was r.datemvt) — CRITICAL
- qte: r.qtemvt (was r.qte) — CRITICAL
- montant: r.mntmvtht (was r.montant) — CRITICAL
- marge: r.margemvt (was r.marge) — CRITICAL
- URL now uses dateDebut/dateFin params (confirmed working vs datedeb/datefin which ignores filter)

Sites fallback: use real codes 292/579 (Frouard/Houdemont)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 15:03:19 +01:00
MichaelandClaude Sonnet 4.6 c33e22f7eb fix: extractList includes API-specific wrapper keys, diag uses real codefou
- extractList now explicitly checks "mouvements", "articles", "fournisseurs",
  "ventes", "stocks", "commandes" wrapper keys before generic array fallback
- Diag endpoint auto-fetches first real codefou from fournisseurs instead
  of hardcoded "AUXENCE" (which was supplier nom, not actual codefou)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-18 14:57:49 +01:00
Michael c056750ea7 feat: implement FF Nancy API client including data models and functions for suppliers, articles, movements, and stock. 2026-03-18 14:44:44 +01:00
Michael 1035489db1 feat: Add FF Nancy API client and status endpoint, implement grid product fetching and draft change saving, and introduce AI Copilot core logic. 2026-03-18 14:31:29 +01:00