fix: MoM mes-en-curso al mes previo real y pipelines CRM históricos

El filtro Online se aplica por rango de fechas; backfill de pipelines para que agosto/YoY no queden en 4 ventas. MoM de «este mes» usa los mismos días del mes anterior.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
4Ventures
2026-09-28 12:46:08 +02:00
parent 5235c88c13
commit 83e2b59e83
2 changed files with 232 additions and 12 deletions

View File

@@ -252,6 +252,23 @@ export function buildRangeDeltas(
);
momSince = isoDate(prevMonthStart);
momUntil = prevMonthEnd;
} else if (
sinceD.getUTCDate() === 1 &&
sinceD.getUTCMonth() === untilD.getUTCMonth() &&
sinceD.getUTCFullYear() === untilD.getUTCFullYear()
) {
// Month-to-date (e.g. 1–27 sep) → same days previous calendar month (1–27 ago).
const prev = new Date(
Date.UTC(sinceD.getUTCFullYear(), sinceD.getUTCMonth() - 1, 1)
);
momSince = isoDate(prev);
const prevLast = new Date(
Date.UTC(prev.getUTCFullYear(), prev.getUTCMonth() + 1, 0)
).getUTCDate();
const day = Math.min(untilD.getUTCDate(), prevLast);
momUntil = isoDate(
new Date(Date.UTC(prev.getUTCFullYear(), prev.getUTCMonth(), day))
);
} else {
momUntil = shiftIsoDays(since, -1);
momSince = shiftIsoDays(momUntil, -(span - 1));
@@ -557,15 +574,17 @@ export function filterDealsForRange(
since: string | null,
until: string | null
): DealWonRow[] {
const won = preferOnlinePaidDeals(
deals.filter((d) => !d.stage || d.stage === 'won')
);
if (!since || !until) return won;
return won.filter((d) => {
const day = (d.won_at || '').slice(0, 10);
if (!day) return false;
return day >= since && day <= until;
});
const won = deals.filter((d) => !d.stage || d.stage === 'won');
const inRange =
since && until
? won.filter((d) => {
const day = (d.won_at || '').slice(0, 10);
if (!day) return false;
return day >= since && day <= until;
})
: won;
// Online filter after the date window so MoM/YoY months are independent.
return preferOnlinePaidDeals(inRange);
}
/** Overlay CRM won deals onto ad spend/leads totals. */
@@ -757,9 +776,8 @@ export function resolveWonCohort(
deals: DealWonRow[],
leads: CrmLeadRow[]
): { deals: DealWonRow[]; source: 'deals' | 'cliente_leads' | 'none' } {
const won = preferOnlinePaidDeals(
deals.filter((d) => !d.stage || d.stage === 'won')
);
// Keep all won deals here; Online/paid filter runs per date range.
const won = deals.filter((d) => !d.stage || d.stage === 'won');
if (won.length) return { deals: won, source: 'deals' };
const fromLeads = clienteLeadsAsWonDeals(leads);
if (fromLeads.length) return { deals: fromLeads, source: 'cliente_leads' };