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>
This commit is contained in:
MichaelandClaude Sonnet 4.6 committed 2026-03-19 22:02:12 +01:00
1 parent 383b8ccac7
commit 65f455b4e2
2 files changed
+34 -53

No files matched your search

+14 -5
View File
@@ -29,16 +29,25 @@ export async function getProductRows(input: GetProductRowsInput): Promise<Produc
const articles = await getArticlesByFournisseur(codeFournisseur);
console.log(`[getProductRows] ${articles.length} articles for ${codeFournisseur}`);
// ─── Phase 2 : Mensuel + Commandes (en parallèle) ────────────────────
// ─── Phase 2A : Mensuel + Commandes (en parallèle) ──────────────────
// Mensuel d'abord pour identifier quels articles ont des ventes.
// Referentiel et Ranking ensuite, seulement pour ces articles.
const { dateDebut, dateFin } = buildLast12MonthsRange();
const [mensuelMap, referentielMap, commandesMap, rankingResult] = await Promise.all([
const [mensuelMap, commandesMap] = await Promise.all([
getMensuelByArticles(articles, dateDebut, dateFin),
getReferentielByArticles(articles),
getCommandesByFournisseur(codeFournisseur),
getRankingByArticles(articles, codeFournisseur),
]);
console.log(`[getProductRows] mensuel data for ${mensuelMap.size}/${articles.length} articles`);
// ─── Phase 2B : Referentiel + Ranking uniquement pour articles avec ventes ──
// Réduit drastiquement les appels API pour les gros fournisseurs.
const articlesWithData = articles.filter(a => mensuelMap.has(a.codein));
console.log(`[getProductRows] articles avec ventes: ${articlesWithData.length}/${articles.length}`);
const [referentielMap, rankingResult] = await Promise.all([
getReferentielByArticles(articlesWithData),
getRankingByArticles(articlesWithData, codeFournisseur),
]);
const { rankings: rankingMap, totalRankedProducts } = rankingResult;
console.log(`[getProductRows] mensuel data for ${mensuelMap.size}/${articles.length} articles`);
// ─── Phase 3 : Fenêtre temporelle (12 mois complets) ─────────────────
const now = new Date();