From 888a02f39722c68e4beddefbd1e39c402dfa51cb Mon Sep 17 00:00:00 2001 From: kewldan Date: Tue, 28 Jul 2026 21:23:08 +0300 Subject: [PATCH] =?UTF-8?q?fix(subscription):=20=D0=BA=D0=BE=D1=80=D1=80?= =?UTF-8?q?=D0=B5=D0=BA=D1=82=D0=BD=D0=B0=D1=8F=20=D1=86=D0=B5=D0=BD=D0=B0?= =?UTF-8?q?=20=D0=B7=D0=B0=20=D0=BC=D0=B5=D1=81=D1=8F=D1=86=20=D0=BF=D1=80?= =?UTF-8?q?=D0=B8=20=D0=B2=D1=8B=D0=B1=D0=BE=D1=80=D0=B5=20=D0=BF=D0=B5?= =?UTF-8?q?=D1=80=D0=B8=D0=BE=D0=B4=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Для периодов короче месяца в карточке периода под ценой выводилась та же сумма с подписью «/мес»: цена за 7 дней показывалась как цена за месяц. Причина — деление на max(1, days / 30), которое для коротких периодов даёт делитель 1. Расчёт вынесен в getMonthlyPriceKopeks: месячная ставка считается пропорцией (price * 30 / days) и не показывается для периодов в месяц и короче, где она либо дублирует цену, либо вводит в заблуждение. Тот же хелпер применён на экране продления, где месячная цена для периодов вроде 45 дней считалась делением на округлённое число месяцев. --- .../purchase/TariffPurchaseForm.tsx | 14 +++++----- src/pages/RenewSubscription.tsx | 6 ++--- src/utils/pricing.test.ts | 26 +++++++++++++++++++ src/utils/pricing.ts | 15 +++++++++++ 4 files changed, 51 insertions(+), 10 deletions(-) create mode 100644 src/utils/pricing.test.ts create mode 100644 src/utils/pricing.ts diff --git a/src/components/subscription/purchase/TariffPurchaseForm.tsx b/src/components/subscription/purchase/TariffPurchaseForm.tsx index d49a918..a234f11 100644 --- a/src/components/subscription/purchase/TariffPurchaseForm.tsx +++ b/src/components/subscription/purchase/TariffPurchaseForm.tsx @@ -8,6 +8,7 @@ import { useCurrency } from '../../../hooks/useCurrency'; import { usePromoDiscount } from '../../../hooks/usePromoDiscount'; import { usePlatform } from '../../../platform'; import { openPaymentUrl } from '../../../utils/openPaymentUrl'; +import { getMonthlyPriceKopeks } from '../../../utils/pricing'; import InsufficientBalancePrompt from '../../InsufficientBalancePrompt'; import type { Tariff, TariffPeriod } from '../../../types'; @@ -279,10 +280,7 @@ export function TariffPurchaseForm({ const displayDiscount = promoPeriod.percent; const displayOriginal = promoPeriod.original; const displayPrice = promoPeriod.price; - const displayPerMonth = - displayPrice !== period.price_kopeks - ? Math.round(displayPrice / Math.max(1, period.days / 30)) - : period.price_per_month_kopeks; + const displayPerMonth = getMonthlyPriceKopeks(displayPrice, period.days); return ( ); })} diff --git a/src/pages/RenewSubscription.tsx b/src/pages/RenewSubscription.tsx index 8b9ea7e..ebcc461 100644 --- a/src/pages/RenewSubscription.tsx +++ b/src/pages/RenewSubscription.tsx @@ -5,6 +5,7 @@ import { Navigate, useNavigate, useParams } from 'react-router'; import { subscriptionApi } from '../api/subscription'; import { useTheme } from '../hooks/useTheme'; import { getGlassColors } from '../utils/glassTheme'; +import { getMonthlyPriceKopeks } from '../utils/pricing'; import { useCurrency } from '../hooks/useCurrency'; import { useHaptic } from '../platform'; import InsufficientBalancePrompt from '../components/InsufficientBalancePrompt'; @@ -143,8 +144,7 @@ export default function RenewSubscription() { {options.map((option) => { const isSelected = selectedPeriod === option.period_days; const canAfford = balanceKopeks >= option.price_kopeks; - const months = Math.max(1, Math.round(option.period_days / 30)); - const perMonth = option.price_kopeks / months; + const perMonth = getMonthlyPriceKopeks(option.price_kopeks, option.period_days); return (