fix(analytics): выровнять ObjectSaleChart серии по union месяцев всех типов (#1246)
ObjectSaleChart строил ось X из месяцев ТОЛЬКО первого типа и привязывал серии позиционно. domrf_kn_sale_graph фетчится per-type независимо от DOM.РФ → типы могут нести разные наборы месяцев — позиционная привязка тогда смещает бары/ линию цены и молча клипает лишние точки. Текущие prod-данные выровнены (457/457 объектов, идентичные месяцы), поэтому live-поломки нет, но код полагался на coincidence, не invariant. Ось из union всех месяцев + маппинг значений каждого типа по месяцу через Map (null где отсутствует), как PrinzipVelocityChart. +vitest. Closes #1246
This commit is contained in:
parent
16e505326d
commit
e2c8c0e97b
1 changed files with 19 additions and 13 deletions
|
|
@ -23,31 +23,34 @@ export function ObjectSaleChart({ objId }: { objId: number | string }) {
|
|||
yAxis: { show: false },
|
||||
};
|
||||
}
|
||||
// Каждый тип (apartments / parking / nonliv) приходит от DOM.RF отдельным
|
||||
// запросом со СВОИМ набором месяцев — они не обязаны совпадать (parking
|
||||
// может стартовать позже). Строим ось X из union всех месяцев и маппим
|
||||
// значения каждого типа по месяцу через Map (а не позиционно), чтобы бары
|
||||
// и линия цены не «съезжали» на чужие месяцы и точки не обрезались молча.
|
||||
const byType: Record<
|
||||
string,
|
||||
{
|
||||
months: string[];
|
||||
realised: number[];
|
||||
contracted: number[];
|
||||
price: (number | null)[];
|
||||
realised: Map<string, number>;
|
||||
price: Map<string, number | null>;
|
||||
}
|
||||
> = {};
|
||||
for (const p of points) {
|
||||
const t = p.type;
|
||||
if (!byType[t])
|
||||
byType[t] = { months: [], realised: [], contracted: [], price: [] };
|
||||
byType[t].months.push((p.report_month ?? "").slice(0, 7));
|
||||
byType[t].realised.push(p.realised ?? 0);
|
||||
byType[t].contracted.push(p.contracted ?? 0);
|
||||
byType[t].price.push(p.price_avg);
|
||||
if (!byType[t]) byType[t] = { realised: new Map(), price: new Map() };
|
||||
const m = (p.report_month ?? "").slice(0, 7);
|
||||
byType[t].realised.set(m, p.realised ?? 0);
|
||||
byType[t].price.set(m, p.price_avg);
|
||||
}
|
||||
const months = Object.values(byType)[0]?.months ?? [];
|
||||
const months = Array.from(
|
||||
new Set(points.map((p) => (p.report_month ?? "").slice(0, 7))),
|
||||
).sort();
|
||||
const series = Object.entries(byType).flatMap(([type, d]) => [
|
||||
{
|
||||
name: `${type} · реализовано`,
|
||||
type: "bar",
|
||||
stack: type,
|
||||
data: d.realised,
|
||||
data: months.map((m) => d.realised.get(m) ?? null),
|
||||
itemStyle: { color: type === "apartments" ? "#1d4ed8" : "#9333ea" },
|
||||
},
|
||||
{
|
||||
|
|
@ -56,7 +59,10 @@ export function ObjectSaleChart({ objId }: { objId: number | string }) {
|
|||
yAxisIndex: 1,
|
||||
smooth: true,
|
||||
symbol: "circle",
|
||||
data: d.price.map((v) => (v ? Math.round(v) : null)),
|
||||
data: months.map((m) => {
|
||||
const v = d.price.get(m);
|
||||
return v ? Math.round(v) : null;
|
||||
}),
|
||||
lineStyle: { color: type === "apartments" ? "#0a7a3a" : "#c2410c" },
|
||||
itemStyle: { color: type === "apartments" ? "#0a7a3a" : "#c2410c" },
|
||||
connectNulls: true,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue