mirror of
https://github.com/chillpadclub/bedolaga-cabinet.git
synced 2026-09-16 01:33:09 +00:00
fix(subscription): корректная цена за месяц при выборе периода
Для периодов короче месяца в карточке периода под ценой выводилась та же сумма с подписью «/мес»: цена за 7 дней показывалась как цена за месяц. Причина — деление на max(1, days / 30), которое для коротких периодов даёт делитель 1. Расчёт вынесен в getMonthlyPriceKopeks: месячная ставка считается пропорцией (price * 30 / days) и не показывается для периодов в месяц и короче, где она либо дублирует цену, либо вводит в заблуждение. Тот же хелпер применён на экране продления, где месячная цена для периодов вроде 45 дней считалась делением на округлённое число месяцев.
This commit is contained in:
26
src/utils/pricing.test.ts
Normal file
26
src/utils/pricing.test.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { getMonthlyPriceKopeks } from './pricing';
|
||||
|
||||
describe('getMonthlyPriceKopeks', () => {
|
||||
it('hides the monthly rate for periods of a month or shorter', () => {
|
||||
expect(getMonthlyPriceKopeks(4830, 7)).toBeNull();
|
||||
expect(getMonthlyPriceKopeks(9900, 14)).toBeNull();
|
||||
expect(getMonthlyPriceKopeks(16030, 30)).toBeNull();
|
||||
});
|
||||
|
||||
it('divides by whole months for multiples of 30 days', () => {
|
||||
expect(getMonthlyPriceKopeks(30000, 90)).toBe(10000);
|
||||
expect(getMonthlyPriceKopeks(60000, 180)).toBe(10000);
|
||||
});
|
||||
|
||||
it('prorates periods that are not whole months', () => {
|
||||
expect(getMonthlyPriceKopeks(15000, 45)).toBe(10000);
|
||||
expect(getMonthlyPriceKopeks(100000, 365)).toBe(8219);
|
||||
});
|
||||
|
||||
it('returns null for non-finite input', () => {
|
||||
expect(getMonthlyPriceKopeks(Number.NaN, 90)).toBeNull();
|
||||
expect(getMonthlyPriceKopeks(30000, Number.NaN)).toBeNull();
|
||||
expect(getMonthlyPriceKopeks(30000, Number.POSITIVE_INFINITY)).toBeNull();
|
||||
});
|
||||
});
|
||||
15
src/utils/pricing.ts
Normal file
15
src/utils/pricing.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
/** Длина «месяца» в днях — тот же множитель, что использует бэкенд при расчёте цены за месяц. */
|
||||
const DAYS_IN_MONTH = 30;
|
||||
|
||||
/**
|
||||
* Цена за месяц (в копейках) для периода длиной `days` дней.
|
||||
*
|
||||
* Возвращает `null`, когда месячная ставка не имеет смысла: для периода
|
||||
* в месяц и короче она либо повторяет цену периода (30 дней), либо
|
||||
* выдаёт цену периода за месячную (7 дней → цена семи дней «за месяц»).
|
||||
*/
|
||||
export function getMonthlyPriceKopeks(priceKopeks: number, days: number): number | null {
|
||||
if (!Number.isFinite(priceKopeks) || !Number.isFinite(days)) return null;
|
||||
if (days <= DAYS_IN_MONTH) return null;
|
||||
return Math.round((priceKopeks * DAYS_IN_MONTH) / days);
|
||||
}
|
||||
Reference in New Issue
Block a user