mirror of
https://github.com/R0m1k3/CollectFlow.git
synced 2026-10-21 22:18:08 +02:00
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>
This commit is contained in:
1 parent
be3a196744
commit
1cd3ade77e
2 files changed
+16
-20
No files matched your search
@@ -26,26 +26,16 @@ export async function getProductRows(input: GetProductRowsInput): Promise<Produc
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// ─── Phase 1 : Articles du fournisseur ───────────────────────────────
|
// ─── Phase 1 : Articles du fournisseur ───────────────────────────────
|
||||||
const allArticles = await getArticlesByFournisseur(codeFournisseur);
|
const articles = await getArticlesByFournisseur(codeFournisseur);
|
||||||
console.log(`[getProductRows] ${allArticles.length} articles for ${codeFournisseur}`);
|
console.log(`[getProductRows] ${articles.length} articles for ${codeFournisseur}`);
|
||||||
|
|
||||||
// Filtrer les articles actifs et non-suspendus pour les appels coûteux (mensuel/referentiel)
|
|
||||||
// Les articles inactifs/suspendus restent dans la grille mais sans données de vente
|
|
||||||
const activeArticles = allArticles.filter(a => a.suspendu !== true && a.actif !== false);
|
|
||||||
const suspendedCount = allArticles.length - activeArticles.length;
|
|
||||||
if (suspendedCount > 0) {
|
|
||||||
console.log(`[getProductRows] Filtrage: ${activeArticles.length} actifs, ${suspendedCount} suspendus/inactifs exclus des appels API`);
|
|
||||||
}
|
|
||||||
// On utilise allArticles pour la grille, activeArticles pour mensuel/referentiel
|
|
||||||
const articles = allArticles;
|
|
||||||
|
|
||||||
// ─── Phase 2 : Mensuel + Commandes (en parallèle) ────────────────────
|
// ─── Phase 2 : Mensuel + Commandes (en parallèle) ────────────────────
|
||||||
const { dateDebut, dateFin } = buildLast12MonthsRange();
|
const { dateDebut, dateFin } = buildLast12MonthsRange();
|
||||||
const [mensuelMap, referentielMap, commandesMap, rankingResult] = await Promise.all([
|
const [mensuelMap, referentielMap, commandesMap, rankingResult] = await Promise.all([
|
||||||
getMensuelByArticles(activeArticles, dateDebut, dateFin),
|
getMensuelByArticles(articles, dateDebut, dateFin),
|
||||||
getReferentielByArticles(activeArticles),
|
getReferentielByArticles(articles),
|
||||||
getCommandesByFournisseur(codeFournisseur),
|
getCommandesByFournisseur(codeFournisseur),
|
||||||
getRankingByArticles(activeArticles, codeFournisseur),
|
getRankingByArticles(articles, codeFournisseur),
|
||||||
]);
|
]);
|
||||||
const { rankings: rankingMap, totalRankedProducts } = rankingResult;
|
const { rankings: rankingMap, totalRankedProducts } = rankingResult;
|
||||||
console.log(`[getProductRows] mensuel data for ${mensuelMap.size}/${articles.length} articles`);
|
console.log(`[getProductRows] mensuel data for ${mensuelMap.size}/${articles.length} articles`);
|
||||||
@@ -268,9 +258,15 @@ export async function getProductRows(input: GetProductRowsInput): Promise<Produc
|
|||||||
console.error("[getProductRows] Snapshot restore error:", snapErr);
|
console.error("[getProductRows] Snapshot restore error:", snapErr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ─── Phase 7 : Score composite ────────────────────────────────────────
|
// ─── Phase 8 : Filtrer les produits Y sans ventes ────────────────────
|
||||||
const rows = Array.from(productMap.values());
|
// Les produits en gamme Y sans aucune vente sur 12 mois sont exclus de la grille
|
||||||
console.log(`[getProductRows] ${rows.length} produits, ${mensuelMap.size} avec données`);
|
// pour alléger le chargement. Exception : produits Y avec ventes conservés.
|
||||||
|
const allRows = Array.from(productMap.values());
|
||||||
|
const rows = allRows.filter(p =>
|
||||||
|
p.codeGamme !== "Y" || p.totalQuantite > 0
|
||||||
|
);
|
||||||
|
const excludedY = allRows.length - rows.length;
|
||||||
|
console.log(`[getProductRows] ${rows.length} produits (${excludedY} gamme Y sans ventes exclus), ${mensuelMap.size} avec données`);
|
||||||
return computeProductScores(rows);
|
return computeProductScores(rows);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@@ -326,7 +326,7 @@ export async function getMensuelByArticles(
|
|||||||
articles: FfArticle[],
|
articles: FfArticle[],
|
||||||
dateDebut: string,
|
dateDebut: string,
|
||||||
dateFin: string,
|
dateFin: string,
|
||||||
batchSize = 20
|
batchSize = 50
|
||||||
): Promise<Map<string, FfMensuelEntry[]>> {
|
): Promise<Map<string, FfMensuelEntry[]>> {
|
||||||
const result = new Map<string, FfMensuelEntry[]>();
|
const result = new Map<string, FfMensuelEntry[]>();
|
||||||
|
|
||||||
@@ -412,7 +412,7 @@ export interface FfReferentiel {
|
|||||||
*/
|
*/
|
||||||
export async function getReferentielByArticles(
|
export async function getReferentielByArticles(
|
||||||
articles: FfArticle[],
|
articles: FfArticle[],
|
||||||
batchSize = 20
|
batchSize = 50
|
||||||
): Promise<Map<string, FfReferentiel>> {
|
): Promise<Map<string, FfReferentiel>> {
|
||||||
const result = new Map<string, FfReferentiel>();
|
const result = new Map<string, FfReferentiel>();
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user