НДС в DI2: порядок тултипа графика, компактный виджет контроля квартала

- Тултип «Динамики НДС»: порядок Начислено за месяц → Вычет за месяц → К уплате за месяц
  → Накоплено за квартал; линии переименованы с уточнением «за месяц»
- «Контроль квартала»: высота таблицы ~5 строк с вертикальной прокруткой (как у трекера),
  убран список «Оплачено, аванс не висячий»
This commit is contained in:
2026-09-29 16:11:40 +03:00
parent 4d1dc2b6f9
commit f6e391d588

View File

@@ -595,12 +595,19 @@ function formatQuarterLabel(q: string): string {
return `${q.slice(0, 4)} Q${quarter}`;
}
function ChartTooltip({ active, payload, label, formatValue }: any) {
function ChartTooltip({ active, payload, label, formatValue, seriesOrder }: any) {
if (!active || !payload?.length) return null;
const items = seriesOrder
? [...payload].sort((a: any, b: any) => {
const ia = seriesOrder.indexOf(a.dataKey);
const ib = seriesOrder.indexOf(b.dataKey);
return (ia === -1 ? 999 : ia) - (ib === -1 ? 999 : ib);
})
: payload;
return (
<div className="bg-popover border border-border rounded-md px-3 py-2 shadow-md">
<p className="text-sm font-medium text-foreground mb-2">{label}</p>
{payload.map((entry: any) => (
{items.map((entry: any) => (
<div key={entry.dataKey} className="flex items-center gap-2 text-sm py-0.5">
<div className="w-2.5 h-2.5 rounded-sm shrink-0" style={{ backgroundColor: entry.color }} />
<span className="text-muted-foreground">{entry.name}</span>
@@ -688,7 +695,6 @@ function VatTab({ data, quarters, balance, sync, tracker, quarterControl }: {
const purchasesByRate = (data.byRate ?? []).filter((r: any) => r.direction === "purchases");
const quarter = data.currentQuarter ?? null;
const redHanging: any[] = quarterControl?.redHanging ?? [];
const redNoAdvance: any[] = quarterControl?.redNoAdvance ?? [];
const contractTotals = quarterControl?.totals ?? null;
const markerCounts: any[] = quarterControl?.byMarker ?? [];
const allContractRows: any[] = allContractsQuery.data?.rows ?? [];
@@ -795,14 +801,24 @@ function VatTab({ data, quarters, balance, sync, tracker, quarterControl }: {
tickLine={false}
/>
<YAxis tick={{ fontSize: 11 }} axisLine={false} tickLine={false} tickFormatter={tickFormatter} />
<Tooltip content={(props: any) => <ChartTooltip {...props} label={periodLabel(props.label)} />} />
<Tooltip
content={(props: any) => (
<ChartTooltip
{...props}
label={periodLabel(props.label)}
seriesOrder={groupBy === "month"
? ["accrued", "deducted", "toPay", "vatCumulative"]
: ["accrued", "deducted", "toPay"]}
/>
)}
/>
<Legend wrapperStyle={{ fontSize: 11, paddingTop: 8 }} />
{groupBy === "month" ? (
<>
<Bar dataKey="toPay" name="К уплате за месяц" fill={COLORS.toPay} radius={[3, 3, 0, 0]} />
<Bar dataKey="vatCumulative" name="Накоплено за квартал" fill={COLORS.cumulative} radius={[3, 3, 0, 0]} />
<Line dataKey="accrued" name="Начислено" stroke={COLORS.income} strokeWidth={2} dot={{ r: 2 }} />
<Line dataKey="deducted" name="Вычет" stroke={COLORS.expense} strokeWidth={2} dot={{ r: 2 }} />
<Line dataKey="accrued" name="Начислено за месяц" stroke={COLORS.income} strokeWidth={2} dot={{ r: 2 }} />
<Line dataKey="deducted" name="Вычет за месяц" stroke={COLORS.expense} strokeWidth={2} dot={{ r: 2 }} />
</>
) : (
<>
@@ -962,7 +978,7 @@ function VatTab({ data, quarters, balance, sync, tracker, quarterControl }: {
) : (
<div className="space-y-3">
{redHanging.length > 0 ? (
<div className="max-h-[264px] overflow-y-auto overflow-x-auto">
<div className="max-h-[220px] overflow-y-auto overflow-x-auto">
<table className="w-full table-fixed text-sm">
<thead className="sticky top-0 z-10 bg-background">
<tr className="text-xs text-muted-foreground border-b border-border">
@@ -990,19 +1006,6 @@ function VatTab({ data, quarters, balance, sync, tracker, quarterControl }: {
<p className="text-sm text-muted-foreground">Договоров с висячим авансом и без отгрузки нет</p>
)}
{redNoAdvance.length > 0 && (
<div>
<p className="text-xs font-medium text-muted-foreground mb-1">
Оплачено, аванс не висячий — проверить зачёт у бухгалтерии ({redNoAdvance.length}):
</p>
<div className="flex flex-wrap gap-x-4 gap-y-0.5 text-xs text-muted-foreground">
{redNoAdvance.map((r: any, i: number) => (
<span key={i} className="tabular-nums">{r.counterparty} — {formatCurrency(r.paid)}</span>
))}
</div>
</div>
)}
<div className="flex items-center justify-between flex-wrap gap-2 pt-1">
<p className="text-xs text-muted-foreground">
Итого по списку: {redHanging.length} договоров, сумма авансов {formatCurrency(redHangingAdvanceSum)}