food-market/CLAUDE.md
nns fd2f5ae4f3 Phase 0: project scaffolding and end-to-end auth
- .NET 8 LTS solution with 7 projects (domain/application/infrastructure/api/shared/pos.core/pos[WPF])
- Central package management (Directory.Packages.props), .editorconfig, global.json pin to 8.0.417
- PostgreSQL 14 dev DB via existing brew service; food_market database created
- ASP.NET Identity + OpenIddict 5 (password + refresh token flows) with ephemeral dev keys
- EF Core 8 + Npgsql; multi-tenant query filter via reflection over ITenantEntity
- Initial migration: 13 tables (Identity + OpenIddict + organizations)
- AuthorizationController implements /connect/token; seeders create demo org + admin
- Protected /api/me endpoint returns current user + org claims
- React 19 + Vite 8 + Tailwind v4 SPA with TanStack Query, React Router 7
- Login flow with dev-admin placeholder, bearer interceptor + refresh token fallback
- docs/architecture.md, CLAUDE.md, README.md

Verified end-to-end: health check, password grant issues JWT with org_id,
web app builds successfully (310 kB gzipped).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 13:59:13 +05:00

102 lines
5.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# food-market — project guide for Claude
Аналог системы МойСклад для розничной торговли в Казахстане. Multi-tenant сервер + web-админка + Windows-касса.
## Naming
- **Брендинг lowercase везде:** папки, файлы, csproj, docker-образы, репо → `food-market`, `food-market.api`.
- **C# namespaces** — `foodmarket.Api`, `foodmarket.Domain`, `foodmarket.Infrastructure` и т.д. (C# не допускает дефис, поэтому `foodmarket` одним словом).
- **Отображаемое имя в UI** — "Food Market" или "food-market" в техн. контекстах.
## Стек
| Слой | Технология |
|---|---|
| Backend | .NET 8 LTS, ASP.NET Core, EF Core 8, PostgreSQL 14+ |
| Auth | OpenIddict 5 (password + refresh), ASP.NET Identity |
| Backend libs | MediatR, FluentValidation, Mapster (НЕ AutoMapper — тот стал платным + CVE), Serilog, Hangfire, SignalR |
| Web | React 19 + Vite + TypeScript 6, Tailwind CSS v4, shadcn/ui, TanStack Query, TanStack Table, AG Grid Community, react-hook-form + Zod |
| POS | WPF на .NET 8 (Windows 10+), CommunityToolkit.Mvvm, SQLite, Refit + Polly, System.IO.Ports для весов |
**Запрет на платные компоненты:** никаких Kendo UI, DevExpress, Syncfusion commercial, Telerik в новом коде. Если задача требует такой компонент — сначала спросить.
## Структура
```
food-market/
├── src/
│ ├── food-market.domain/ # чистые POCO, enum'ы, доменные события (никакого ASP.NET, EF)
│ ├── food-market.application/ # MediatR handlers, DTO, FluentValidation, интерфейсы
│ ├── food-market.infrastructure/ # EF Core, Identity, OpenIddict EF store, внешние сервисы
│ ├── food-market.api/ # ASP.NET Core, контроллеры, OpenIddict server
│ ├── food-market.web/ # React + Vite SPA
│ ├── food-market.shared/ # DTO-контракты сервер ↔ POS
│ ├── food-market.pos.core/ # логика POS (независима от UI)
│ └── food-market.pos/ # WPF (net8.0-windows, сборка возможна на macOS)
├── tests/
├── deploy/
│ └── docker-compose.yml # Postgres 16 для прод/Linux
├── docs/
└── food-market.sln
```
## Мультитенантность (важно)
Каждая доменная сущность реализует `ITenantEntity` (есть `OrganizationId`). `AppDbContext` применяет query filter автоматически через reflection — запросы видят только данные своей организации. `SuperAdmin` роль видит всё.
Tenant определяется из JWT claim `org_id`, который выдаётся при логине. См. `HttpContextTenantContext` в api.
**При создании новой сущности:**
1. Если данные относятся к магазину — наследовать от `TenantEntity`.
2. Если общие справочники (единицы измерения, страны) — от `Entity`.
3. Справочник организаций (`Organization`) — от `Entity` (сама по себе не tenant-scoped).
## БД для dev
Используется существующий **postgres@14** из brew (порт 5432). БД `food_market`, owner `nns`, пароль пустой.
Connection string в `appsettings.Development.json`. Для прода/Linux будет postgres@16 через `deploy/docker-compose.yml` (порт 5433 чтобы не конфликтовать).
**НЕ переключать systemwide postgres версию** — это сломает смежные проекты (calcman, purchase, makesales, food-market-server).
## Миграции EF Core
```bash
# Создать миграцию
dotnet ef migrations add <Name> \
--project src/food-market.infrastructure \
--startup-project src/food-market.api \
--output-dir Persistence/Migrations
# Применить
dotnet ef database update \
--project src/food-market.infrastructure \
--startup-project src/food-market.api
```
## Запуск dev
```bash
# API (http://localhost:5081)
ASPNETCORE_ENVIRONMENT=Development dotnet run --project src/food-market.api
# Web (http://localhost:5173)
cd src/food-market.web && pnpm dev
# Проверить здоровье
curl http://localhost:5081/health
# Получить токен (dev admin)
curl -X POST http://localhost:5081/connect/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=password&username=admin@food-market.local&password=Admin12345!&client_id=food-market-web&scope=openid profile email roles api"
```
## Соседние проекты (НЕ ломать)
В `~/Documents/devprojects/` есть: `food-market-server`, `food-market-app`, `calcman`, `purchase`, `makesales`. Любые изменения глобальных инструментов (nvm default, postgres CLI версия, .NET SDK) — только с подтверждения пользователя.
## Источник правды по функциональности
МойСклад API: `https://dev.moysklad.ru/doc/api/remap/1.2/`. Перед моделированием новых сущностей в Phase 1+ — подтягивать актуальные разделы через WebFetch для соответствия их логике.