Главное в этом релизе — поддержка возвратов (операций «Возврат по расходным операциям» из Дзен-мани). Раньше они классифицировались как доход и завышали Доход в KPI; теперь это отдельный тип refund, который ведёт себя ровно как в самом Дзене — деньги приходят на счёт, но вычитаются из расхода соответствующей категории, а не прибавляются к доходу.
↩ Возвраты — отдельный тип операций
Дзен-мани с недавних пор различает обычные доходы и возвраты по расходным операциям. Раньше мы их не различали — теперь различаем.
- Автодетект по флагам тега: входящая операция, тегированная расходной категорией (
tag.showOutcome === true && tag.showIncome === false), классифицируется какrefund. Никаких ручных правок — работает с момента следующего pull из облака. - Логика учёта повторяет Дзен:
- расход категории уменьшается на сумму возврата
- доход KPI не растёт — возврат не считается заработком
- баланс счёта корректно увеличивается — деньги реально пришли
- Визуально возврат выделен фиолетовым цветом с глифом
↩(вместо красного−), с тултипом «Возврат — уменьшает расход категории» — заметно отличается от обычных доходов и расходов в ленте, drawer и поиске.
✏ Поддержка в Edit-модалке
В переключателе типа операции появилась 4-я кнопка «Возврат» (с иконкой Undo2 и фиолетовым тоном). Если пользователь импортировал данные из CSV (где Zenmoney-флаги недоступны и автодетект не сработал), он может вручную пометить операцию как возврат.
🔄 Refund-aware агрегации (16 функций)
Пройдена ревизия всего кода, который агрегирует операции — везде, где имеет смысл, возвраты теперь корректно нетят расход:
lib/aggregations.ts: groupByMonth, groupByCategory, computeKPI, buildWaterfall, buildSankey, buildStreamData, yearOverYearMonthly, categoryMonthlySeries, detectMonthSpikes, detectSeasonality, applyCategoryFlags, topPayees (для расходов), groupByHashtag, dailyExpenseMap, cumulativeNetAt, netWorthSeries, accountMonthlyDeltas, balancesByAccount, dailyBalanceSeries, stackedBalanceByAccount.
lib/digest.ts + lib/yearReview.ts: еженедельный/месячный дайджест и годовой отчёт. Раньше aggregate() в дайджесте ошибочно прибавлял возврат к расходу (вместо вычитания) — пофиксено.
Страницы:
- Бюджеты — возврат уменьшает потраченное по категории
- Категории — иерархия + донат + treemap + drill-down учитывают возвраты
- Топ-получатели — возврат уменьшает net-спенд получателя; полностью возвращённые исчезают из топа
- Тренды, Аномалии, Сравнение, Дашборд, Поиск — drill-down включает возвраты, нижние суммы их вычитают
Намеренно оставлено как было (возвраты искажают метрику): topTransactions (крупнейшие траты), detectAnomalies, detectRecurring, statsByDayOfWeek/HourOfWeek, CSV-импорт.
🐛 Bug-fixes
Графики реагируют на смену отчётного периода
Раньше при смене отчётного периода (Настройки → 1 → 11 числа месяца) графики Категорий — donut, treemap, иерархия — не обновлялись: monthStartDay использовался внутри useMemo, но отсутствовал в массиве зависимостей. Затрагивало 8 страниц (Дашборд, Категории, Тренды, Топ, Бюджеты, Календарь, Сравнение, Cashflow). Поправлено: deps-массивы у applyFilters теперь корректные, при смене периода всё пересчитывается.
Все 25 подписей категорий на горизонтальном баре
На странице Категории → «Все категории (клик по бару)» Recharts по умолчанию (interval="preserveEnd") молча выкидывал подписи у верхних баров. Бары были, а лейблов не было. Поставил interval={0} — каждый тик гарантированно рендерится. Та же правка применена на странице Сравнение.
🛠 Общие хелперы (lib/txKindStyle.ts)
Чтобы не дублировать логику в 20+ местах, добавил три хелпера, которые теперь использует вся кодовая база:
affectsExpense(kind)—trueдляexpenseиrefund. Используется вместоkind === "expense"везде, где надо учесть возвраты.expenseDelta(t)— подписанный вклад в расход:+amountдляexpense,−amountдляrefund,0иначе.cashDelta(t)— подписанный вклад в баланс счёта.kindGlyphClass(kind)— CSS-смещение для глифа↩(центрирует по высоте строки).
🎨 Polish
- Treemap с белым шрифтом в обеих темах (раньше в светлой теме был тёмный текст на насыщенных ячейках — плохо читался).
Что НЕ вошло в этот релиз
Работа над двусторонней синхронизацией (push в облако) — feature/zenmoney-push. Будет в одном из следующих минорных релизов.
Установка
Standalone (1 файл, 342 KB): скачайте DzenAnalytics-v0.5.5-standalone.zip, распакуйте, дважды кликните по DzenAnalytics.html.
Из исходников:
git clone https://github.com/DEADover/DzenAnalytics.git
cd DzenAnalytics
npm install
npm run devПолный changelog
Все коммиты v0.5.4 → v0.5.5: v0.5.4...v0.5.5