Implement pricing management functionality and update related components
- Added new endpoints for managing global pricing settings, including retrieval and updates for `PricePerConfigPerQuarter` and `PricePerConfigPerYear`. - Updated `RoleService` and related commands to remove pricing fields from role management, ensuring a clear separation between role configurations and global pricing. - Enhanced the `FactoryResetCommandHandler` to include seeding of pricing settings during a factory reset. - Modified frontend components to support new pricing settings, including forms for creating and updating pricing information. - Updated API documentation to reflect changes in pricing management endpoints and their expected request/response formats. - Adjusted tests to ensure proper coverage for new pricing functionalities and their integration with existing role management features.
This commit is contained in:
@@ -2086,6 +2086,64 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/admin/pricing": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description OK */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["PricingSettingsDto"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
put: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["UpdatePricingSettingsCommand"];
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description OK */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["PricingSettingsDto"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
post?: never;
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/support/roles": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -2108,7 +2166,7 @@ export interface paths {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"application/json": components["schemas"]["SelectableRoleDto"][];
|
||||
"application/json": components["schemas"]["RoleDto"][];
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -3087,10 +3145,6 @@ export interface components {
|
||||
maxConfigs: number | string;
|
||||
/** Format: int32 */
|
||||
maxIpLimit: number | string;
|
||||
/** Format: int32 */
|
||||
pricePerConfigPerQuarter: null | number | string;
|
||||
/** Format: int32 */
|
||||
pricePerConfigPerYear: null | number | string;
|
||||
};
|
||||
CreateRoleRequestBody: {
|
||||
/** Format: uuid */
|
||||
@@ -3257,6 +3311,12 @@ export interface components {
|
||||
/** Format: int32 */
|
||||
pageSize: number | string;
|
||||
};
|
||||
PricingSettingsDto: {
|
||||
/** Format: int32 */
|
||||
pricePerConfigPerQuarter: null | number | string;
|
||||
/** Format: int32 */
|
||||
pricePerConfigPerYear: null | number | string;
|
||||
};
|
||||
PublishInboundBody: {
|
||||
isPublished: boolean;
|
||||
displayName: null | string;
|
||||
@@ -3299,19 +3359,6 @@ export interface components {
|
||||
/** Format: int32 */
|
||||
maxIpLimit: number | string;
|
||||
isSystem: boolean;
|
||||
/** Format: int32 */
|
||||
pricePerConfigPerQuarter?: null | number | string;
|
||||
/** Format: int32 */
|
||||
pricePerConfigPerYear?: null | number | string;
|
||||
};
|
||||
SelectableRoleDto: {
|
||||
/** Format: uuid */
|
||||
id: string;
|
||||
name: string;
|
||||
/** Format: int32 */
|
||||
maxConfigs: number | string;
|
||||
/** Format: int32 */
|
||||
maxIpLimit: number | string;
|
||||
};
|
||||
StatsDto: {
|
||||
/** Format: int32 */
|
||||
@@ -3442,15 +3489,17 @@ export interface components {
|
||||
title: string;
|
||||
body: string;
|
||||
};
|
||||
UpdatePricingSettingsCommand: {
|
||||
/** Format: int32 */
|
||||
pricePerConfigPerQuarter: null | number | string;
|
||||
/** Format: int32 */
|
||||
pricePerConfigPerYear: null | number | string;
|
||||
};
|
||||
UpdateRoleBody: {
|
||||
/** Format: int32 */
|
||||
maxConfigs: number | string;
|
||||
/** Format: int32 */
|
||||
maxIpLimit: number | string;
|
||||
/** Format: int32 */
|
||||
pricePerConfigPerQuarter: null | number | string;
|
||||
/** Format: int32 */
|
||||
pricePerConfigPerYear: null | number | string;
|
||||
};
|
||||
UserSummaryDto: {
|
||||
/** Format: uuid */
|
||||
|
||||
@@ -173,16 +173,12 @@ export type RoleDto = {
|
||||
maxConfigs: number
|
||||
maxIpLimit: number
|
||||
isSystem: boolean
|
||||
pricePerConfigPerQuarter: number | null
|
||||
pricePerConfigPerYear: number | null
|
||||
}
|
||||
|
||||
/** Роль для выбора в заявке на роль (GET /support/roles) — без цены, она видна только админу. */
|
||||
export type SelectableRoleDto = {
|
||||
id: string
|
||||
name: string
|
||||
maxConfigs: number
|
||||
maxIpLimit: number
|
||||
/** Глобальная справочная цена за конфиг (видна только админу) — одна на весь сервис, не per-роль. */
|
||||
export type PricingSettingsDto = {
|
||||
pricePerConfigPerQuarter: number | null
|
||||
pricePerConfigPerYear: number | null
|
||||
}
|
||||
|
||||
export type ActivationRequestAdminDto = {
|
||||
|
||||
@@ -191,6 +191,7 @@ const resources = {
|
||||
users: 'Пользователи',
|
||||
configs: 'Все конфиги',
|
||||
roles: 'Роли',
|
||||
pricing: 'Цены',
|
||||
nodes: 'Ноды',
|
||||
apps: 'Приложения',
|
||||
instructions: 'Инструкции',
|
||||
@@ -253,13 +254,8 @@ const resources = {
|
||||
maxConfigsHint: '−1 = без лимита.',
|
||||
maxIpLimit: 'Лимит IP на конфиг',
|
||||
maxIpLimitHint: '−1 = без лимита. Применяется только к новым конфигам.',
|
||||
pricePerConfigPerQuarter: 'Цена за конфиг / 3 мес',
|
||||
pricePerConfigPerQuarterHint: 'Справочно, видно только админу. Минимальный период оплаты.',
|
||||
pricePerConfigPerYear: 'Цена за конфиг / год',
|
||||
pricePerConfigPerYearHint: 'Справочно, видно только админу. Задаётся отдельно от квартальной цены.',
|
||||
totalPerQuarter: 'Итого / 3 мес',
|
||||
totalPerYear: 'Итого / год',
|
||||
totalValue: 'Итого для роли: {{total}} ₽.',
|
||||
noPrice: '—',
|
||||
system: 'системная',
|
||||
edit: 'Изменить',
|
||||
@@ -270,6 +266,14 @@ const resources = {
|
||||
updated: 'Квота обновлена.',
|
||||
deleted: 'Роль удалена.',
|
||||
},
|
||||
pricing: {
|
||||
title: 'Справочная цена конфига',
|
||||
pricePerConfigPerQuarter: 'Цена за конфиг / 3 мес',
|
||||
pricePerConfigPerQuarterHint: 'Минимальный период оплаты. Видно только админу.',
|
||||
pricePerConfigPerYear: 'Цена за конфиг / год',
|
||||
pricePerConfigPerYearHint: 'Задаётся независимо от квартальной цены (можно сделать скидку за год).',
|
||||
updated: 'Цена обновлена.',
|
||||
},
|
||||
nodes: {
|
||||
create: 'Добавить ноду',
|
||||
name: 'Название',
|
||||
@@ -617,6 +621,7 @@ const resources = {
|
||||
users: 'Users',
|
||||
configs: 'All configs',
|
||||
roles: 'Roles',
|
||||
pricing: 'Pricing',
|
||||
nodes: 'Nodes',
|
||||
apps: 'Apps',
|
||||
instructions: 'Instructions',
|
||||
@@ -679,13 +684,8 @@ const resources = {
|
||||
maxConfigsHint: '−1 = unlimited.',
|
||||
maxIpLimit: 'IP limit per config',
|
||||
maxIpLimitHint: '−1 = unlimited. Applies to new configs only.',
|
||||
pricePerConfigPerQuarter: 'Price per config / 3 months',
|
||||
pricePerConfigPerQuarterHint: 'Reference only, visible to admin only. Minimum billing period.',
|
||||
pricePerConfigPerYear: 'Price per config / year',
|
||||
pricePerConfigPerYearHint: 'Reference only, visible to admin only. Set independently from the quarterly price.',
|
||||
totalPerQuarter: 'Total / 3 months',
|
||||
totalPerYear: 'Total / year',
|
||||
totalValue: 'Total for role: {{total}} ₽.',
|
||||
noPrice: '—',
|
||||
system: 'system',
|
||||
edit: 'Edit',
|
||||
@@ -696,6 +696,14 @@ const resources = {
|
||||
updated: 'Quota updated.',
|
||||
deleted: 'Role deleted.',
|
||||
},
|
||||
pricing: {
|
||||
title: 'Reference config price',
|
||||
pricePerConfigPerQuarter: 'Price per config / 3 months',
|
||||
pricePerConfigPerQuarterHint: 'Minimum billing period. Visible to admin only.',
|
||||
pricePerConfigPerYear: 'Price per config / year',
|
||||
pricePerConfigPerYearHint: 'Set independently from the quarterly price (allows an annual discount).',
|
||||
updated: 'Pricing updated.',
|
||||
},
|
||||
nodes: {
|
||||
create: 'Add node',
|
||||
name: 'Name',
|
||||
|
||||
Reference in New Issue
Block a user