From 8d72e9da2d1b4361d783e902c22292fcbe4c7919 Mon Sep 17 00:00:00 2001 From: nns <278048682+nurdotnet@users.noreply.github.com> Date: Sun, 26 Apr 2026 16:09:02 +0500 Subject: [PATCH] =?UTF-8?q?feat(super-admin):=20=D0=BF=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=BD=D0=B5=D1=81=D1=82=D0=B8=20=D1=81=D0=BF=D1=80=D0=B0=D0=B2?= =?UTF-8?q?=D0=BE=D1=87=D0=BD=D0=B8=D0=BA=20=D0=A1=D1=82=D1=80=D0=B0=D0=BD?= =?UTF-8?q?=20=D0=B2=20=D1=81=D0=B8=D1=81=D1=82=D0=B5=D0=BC=D0=BD=D1=83?= =?UTF-8?q?=D1=8E=20=D0=BA=D0=BE=D0=BD=D1=81=D0=BE=D0=BB=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Country — глобальный справочник (Entity, не TenantEntity), магазины- клиенты выбирают страны из готового списка но не управляют ими. Управление переносится в SuperAdmin консоль. Изменения: - API: POST/PUT /api/catalog/countries теперь Authorize(Roles=SuperAdmin) (раньше был SuperAdmin,Admin). DELETE и так был SuperAdmin. - GET остаётся [Authorize] без роли — нужен tenant'у для селектов в формах создания орги/контрагентов/товаров. - Tenant AppLayout: убран блок «Справочники» с пунктом «Страны». Иконка Globe больше не импортируется в tenant-меню. - Tenant роут /catalog/countries удалён из App.tsx. - В OrganizationSettingsPage ссылка «откройте справочник Страны» заменена на текст «обратитесь к администратору платформы». - SuperAdminLayout: новый блок «Справочники» с пунктом «Страны» (/super-admin/countries). Иконка Globe. - Роут /super-admin/countries использует существующий CountriesPage — компонент unchanged, страница теперь рендерится в SuperAdminLayout. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../Controllers/Catalog/CountriesController.cs | 4 ++-- src/food-market.web/src/App.tsx | 2 +- src/food-market.web/src/components/AppLayout.tsx | 7 +++---- src/food-market.web/src/components/SuperAdminLayout.tsx | 5 ++++- src/food-market.web/src/pages/OrganizationSettingsPage.tsx | 2 +- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/src/food-market.api/Controllers/Catalog/CountriesController.cs b/src/food-market.api/Controllers/Catalog/CountriesController.cs index 0836f84..1227674 100644 --- a/src/food-market.api/Controllers/Catalog/CountriesController.cs +++ b/src/food-market.api/Controllers/Catalog/CountriesController.cs @@ -57,7 +57,7 @@ public async Task> Get(Guid id, CancellationToken ct) return c is null ? NotFound() : Project(c); } - [HttpPost, Authorize(Roles = "SuperAdmin,Admin")] + [HttpPost, Authorize(Roles = "SuperAdmin")] public async Task> Create([FromBody] CountryInput input, CancellationToken ct) { var e = new Country @@ -73,7 +73,7 @@ public async Task> Create([FromBody] CountryInput input return CreatedAtAction(nameof(Get), new { id = e.Id }, Project(e)); } - [HttpPut("{id:guid}"), Authorize(Roles = "SuperAdmin,Admin")] + [HttpPut("{id:guid}"), Authorize(Roles = "SuperAdmin")] public async Task Update(Guid id, [FromBody] CountryInput input, CancellationToken ct) { var e = await _db.Countries.FirstOrDefaultAsync(x => x.Id == id, ct); diff --git a/src/food-market.web/src/App.tsx b/src/food-market.web/src/App.tsx index a42ed0d..e461cd8 100644 --- a/src/food-market.web/src/App.tsx +++ b/src/food-market.web/src/App.tsx @@ -57,6 +57,7 @@ export default function App() { } /> } /> } /> + } /> {/* Tenant-роуты — обычный AppLayout, но с TenantRouteGuard: @@ -73,7 +74,6 @@ export default function App() { } /> } /> } /> - } /> } /> } /> } /> diff --git a/src/food-market.web/src/components/AppLayout.tsx b/src/food-market.web/src/components/AppLayout.tsx index 376ca30..69f34ed 100644 --- a/src/food-market.web/src/components/AppLayout.tsx +++ b/src/food-market.web/src/components/AppLayout.tsx @@ -6,7 +6,7 @@ import { logout } from '@/lib/auth' import { cn } from '@/lib/utils' import { LayoutDashboard, Package, FolderTree, Ruler, Tag, - Users, Warehouse, Store as StoreIcon, Globe, LogOut, Download, UserCog, Shield, ShieldCheck, + Users, Warehouse, Store as StoreIcon, LogOut, Download, UserCog, Shield, ShieldCheck, Boxes, History, TruckIcon, ShoppingCart, Settings, Menu, X, } from 'lucide-react' import { Logo } from './Logo' @@ -49,9 +49,8 @@ function buildNav(isSuperAdmin: boolean): NavSection[] { { group: 'Продажи', items: [ { to: '/sales/retail', icon: ShoppingCart, label: 'Розничные чеки' }, ]}, - { group: 'Справочники', items: [ - { to: '/catalog/countries', icon: Globe, label: 'Страны' }, - ]}, + // Справочники типа «Страны» — глобальные, управляются SuperAdmin'ом + // в системной консоли. В tenant-меню их больше нет. { group: 'Импорт', items: [ { to: '/admin/import/moysklad', icon: Download, label: 'МойСклад' }, ]}, diff --git a/src/food-market.web/src/components/SuperAdminLayout.tsx b/src/food-market.web/src/components/SuperAdminLayout.tsx index 7e926c7..cadbd5d 100644 --- a/src/food-market.web/src/components/SuperAdminLayout.tsx +++ b/src/food-market.web/src/components/SuperAdminLayout.tsx @@ -3,7 +3,7 @@ import { NavLink, Outlet, useLocation, useNavigate } from 'react-router-dom' import { useQuery } from '@tanstack/react-query' import { ShieldCheck, Building, FileClock, HeartPulse, HardDriveDownload, - Settings, Users, LayoutDashboard, LogOut, Menu, X, ChevronDown, + Settings, Users, LayoutDashboard, LogOut, Menu, X, ChevronDown, Globe, } from 'lucide-react' import { api, getOrgOverride, setOrgOverride } from '@/lib/api' import { logout } from '@/lib/auth' @@ -20,6 +20,9 @@ const NAV: NavSection[] = [ { to: '/super-admin/organizations', icon: Building, label: 'Организации' }, { to: '/super-admin/users', icon: Users, label: 'Пользователи', soon: true }, ]}, + { group: 'Справочники', items: [ + { to: '/super-admin/countries', icon: Globe, label: 'Страны' }, + ]}, { group: 'Аудит', items: [ { to: '/super-admin/audit-log', icon: FileClock, label: 'Журнал действий' }, ]}, diff --git a/src/food-market.web/src/pages/OrganizationSettingsPage.tsx b/src/food-market.web/src/pages/OrganizationSettingsPage.tsx index a0176da..758f3e5 100644 --- a/src/food-market.web/src/pages/OrganizationSettingsPage.tsx +++ b/src/food-market.web/src/pages/OrganizationSettingsPage.tsx @@ -100,7 +100,7 @@ export function OrganizationSettingsPage() {

Валюта и ставка НДС берутся из страны ({form.countryCode}) — - чтобы изменить, откройте справочник Страны. + чтобы изменить — обратитесь к администратору платформы (справочник стран управляется в системной консоли).