Enhance pricing validation and update related components
- Added validation logic in `UpdatePricingSettingsCommandValidator` to ensure the annual price does not fall below the equivalent quarterly price, preventing potential pricing discrepancies. - Updated `PricingSettings` model documentation to clarify that both pricing fields represent monthly rates, with calculations for total costs based on the number of months. - Modified frontend components to reflect the new validation, including error messages when the annual price is cheaper than the quarterly price. - Adjusted API documentation to accurately describe the pricing structure and validation rules for the pricing endpoints.
This commit is contained in:
+2
-2
@@ -248,8 +248,8 @@ reject/approve владением тикета не ограничены. Еди
|
||||
| PUT | `/api/admin/roles/{id}` | admin | `{ maxConfigs, maxIpLimit }` | `RoleDto` |
|
||||
| DELETE | `/api/admin/roles/{id}` | admin | — | `204 No Content` (системные `admin`/`user` удалить нельзя) |
|
||||
| PATCH | `/api/admin/users/{id}/role` | admin | `{ roleId }` | `204 No Content` (`409 Roles.CannotRemoveLastAdmin`, если у цели сейчас `admin`, новая роль другая, и это единственный админ) |
|
||||
| GET | `/api/admin/pricing` | admin | — | `PricingSettingsDto` (глобальная справочная цена за конфиг, одна на весь сервис — не per-роль) |
|
||||
| PUT | `/api/admin/pricing` | admin | `{ pricePerConfigPerQuarter?, pricePerConfigPerYear? }` | `PricingSettingsDto` |
|
||||
| GET | `/api/admin/pricing` | admin | — | `PricingSettingsDto` (глобальная справочная цена за конфиг **в месяц**, одна на весь сервис — не per-роль) |
|
||||
| PUT | `/api/admin/pricing` | admin | `{ pricePerConfigPerQuarter?, pricePerConfigPerYear? }` | `PricingSettingsDto` (`409`/`400`, если годовая ставка×12 дешевле квартальной×3) |
|
||||
|
||||
Нет отдельного эндпоинта «активировать напрямую без запроса» — активация только через
|
||||
approve/reject над `ActivationRequest`.
|
||||
|
||||
+17
-6
@@ -305,14 +305,25 @@ UI **настойчиво напоминает** привязать его (ед
|
||||
| Поле | Тип | Заметки |
|
||||
| --------------------------- | ----------------- | --------------------------------------------------- |
|
||||
| `Id` | `Guid` | PK |
|
||||
| `PricePerConfigPerQuarter` | `int?` | Цена за конфиг за минимальный период оплаты (3 месяца), руб. |
|
||||
| `PricePerConfigPerYear` | `int?` | Цена за конфиг за год, руб. Задаётся независимо от квартальной (не производная — позволяет скидку) |
|
||||
| `PricePerConfigPerQuarter` | `int?` | Цена за конфиг **в месяц** при оплате раз в 3 месяца (минимальный период), руб. |
|
||||
| `PricePerConfigPerYear` | `int?` | Цена за конфиг **в месяц** при оплате раз в год, руб. Может быть ниже квартальной (скидка за годовую оплату) |
|
||||
| `UpdatedAt` | `DateTimeOffset` | |
|
||||
|
||||
Итоговая цена для роли = `цена × AppRole.MaxConfigs` (напр. `user` с `MaxConfigs=3`, 200₽/конфиг/3мес →
|
||||
600₽/3мес; 400₽/конфиг/год → 1200₽/год) — считается на фронте (таблица ролей в админке), нигде не
|
||||
хранится. Для ролей с `MaxConfigs = -1` (unlimited, в т.ч. `admin`) итог не считается — отображается
|
||||
как «не задано».
|
||||
Оба поля — ставка **за месяц**, не за весь период целиком. Итог за период = `ставка × число_месяцев ×
|
||||
AppRole.MaxConfigs`, считается на фронте (таблица ролей в админке), нигде не хранится:
|
||||
- 3 месяца = `PricePerConfigPerQuarter × 3 × MaxConfigs`
|
||||
- полгода = `PricePerConfigPerQuarter × 6 × MaxConfigs` (используется квартальная ставка — отдельного
|
||||
полугодового тарифа нет, это просто два квартальных периода подряд)
|
||||
- год = `PricePerConfigPerYear × 12 × MaxConfigs`
|
||||
|
||||
Например, `user` с `MaxConfigs=3`, ставка 200₽/мес по квартальному тарифу → 600₽/3мес, 1200₽/полгода;
|
||||
при равной годовой ставке (200₽/мес) → 2400₽/год (линейный рост, скидки нет). Для ролей с
|
||||
`MaxConfigs = -1` (unlimited, в т.ч. `admin`) итог не считается — отображается как «не задано».
|
||||
|
||||
**Инвариант**: `UpdatePricingSettingsCommandValidator` не даёт сохранить годовую ставку настолько
|
||||
низкой, что итог за год (`×12`) окажется дешевле итога за квартал (`×3`) — иначе выгоднее купить «год»
|
||||
и не продлевать, чем платить за квартал. Формально: `PricePerConfigPerYear × 12 ≥
|
||||
PricePerConfigPerQuarter × 3`.
|
||||
|
||||
`GET/PUT /api/admin/pricing` — только `admin` (в отличие от `RoleDto`, цена никогда не попадает в
|
||||
`GET /api/support/roles`, доступный любому активированному пользователю, — это два независимых DTO).
|
||||
|
||||
Reference in New Issue
Block a user