Enhance role management by adding pricing fields and updating related logic
CI / Backend (build + test) (push) Successful in 1m22s
CI / Frontend (lint + typecheck + build) (push) Successful in 32s

- Updated `CreateRoleCommand` and `UpdateRoleCommand` to include optional pricing fields: `PricePerConfigPerQuarter` and `PricePerConfigPerYear`.
- Modified `RoleEndpoints` to handle the new pricing parameters during role creation and updates.
- Enhanced validation logic in `CreateRoleCommandValidator` and `UpdateRoleCommandValidator` to ensure pricing fields are non-negative when provided.
- Updated `RoleDto` and `SelectableRoleDto` to include pricing information, ensuring proper data handling in API responses.
- Adjusted frontend components to support new pricing fields in role forms and display total costs based on configurations.
- Updated API documentation to reflect changes in role management endpoints and pricing structure.
This commit is contained in:
Leonid Pershin
2026-07-18 19:02:12 +03:00
parent 68781ef183
commit 285d8180c8
29 changed files with 2638 additions and 30 deletions
+7
View File
@@ -18,6 +18,9 @@ function AdminRolesPage() {
const { data, isLoading, isError, refetch } = useQuery({ queryKey: ['admin-roles'], queryFn: listRoles })
const totalPrice = (price: number | null, maxConfigs: number) =>
price == null || maxConfigs < 0 ? t('admin.roles.noPrice') : `${price * maxConfigs}`
const deleteMutation = useMutation({
mutationFn: deleteRole,
onSuccess: async () => {
@@ -52,6 +55,8 @@ function AdminRolesPage() {
<th className="py-2 font-medium">{t('admin.roles.name')}</th>
<th className="py-2 font-medium">{t('admin.roles.maxConfigs')}</th>
<th className="py-2 font-medium">{t('admin.roles.maxIpLimit')}</th>
<th className="py-2 font-medium">{t('admin.roles.totalPerQuarter')}</th>
<th className="py-2 font-medium">{t('admin.roles.totalPerYear')}</th>
<th className="py-2" />
<th className="py-2" />
</tr>
@@ -64,6 +69,8 @@ function AdminRolesPage() {
</td>
<td className="py-2">{role.maxConfigs < 0 ? t('unlimited') : role.maxConfigs}</td>
<td className="py-2">{role.maxIpLimit < 0 ? t('unlimited') : role.maxIpLimit}</td>
<td className="py-2">{totalPrice(role.pricePerConfigPerQuarter, role.maxConfigs)}</td>
<td className="py-2">{totalPrice(role.pricePerConfigPerYear, role.maxConfigs)}</td>
<td className="py-2 text-right">
<Button size="sm" variant="outline" onClick={() => setEditing(role)}>
{t('admin.roles.edit')}