# food-market

![CI](http://127.0.0.1:3000/nns/food-market/actions/workflows/ci.yml/badge.svg)
![Docker API](http://127.0.0.1:3000/nns/food-market/actions/workflows/docker-api.yml/badge.svg)
![Stage verify](http://127.0.0.1:3000/nns/food-market/actions/workflows/stage-verify.yml/badge.svg)
![Regression](http://127.0.0.1:3000/nns/food-market/actions/workflows/regression.yml/badge.svg)
![coverage](./badges/coverage.svg)

Аналог системы МойСклад для розничной торговли в Казахстане.

## Состав системы

- **Сервер** (ASP.NET Core 8 + PostgreSQL) — мультитенантный API, web-админка на React
- **Web-админка** (React 18 + Vite + shadcn/ui) — управление магазином, справочниками, документами, отчётами
- **Кассовая программа** (WPF на .NET 8) — офлайн-работоспособная касса для Windows 10+, синхронизируется с сервером, работает с весами (Масса-К в первую очередь)

## Структура репозитория

```
food-market/
├── src/
│   ├── food-market.domain/          # доменные сущности, enum'ы, события
│   ├── food-market.application/     # use cases (MediatR), DTO, интерфейсы
│   ├── food-market.infrastructure/  # EF Core, PostgreSQL, внешние сервисы
│   ├── food-market.api/             # ASP.NET Core + OpenIddict + SignalR
│   ├── food-market.web/             # React + Vite + shadcn/ui (SPA)
│   ├── food-market.shared/          # DTO-контракты сервер ↔ POS
│   ├── food-market.pos.core/        # логика POS (независима от UI)
│   └── food-market.pos/             # WPF + .NET 8 кассовая программа
├── tests/
├── deploy/
│   ├── docker-compose.yml           # PostgreSQL для локальной разработки
│   └── Dockerfile.api
└── docs/
```

## Именование

- **Папки, проекты, csproj, docker-образы, URL** — lowercase: `food-market`, `food-market.api`
- **C# namespace** — `foodmarket.Api`, `foodmarket.Domain` (lowercase root; C# не допускает дефис в идентификаторах)
- **Отображаемое имя в UI** — "Food Market"

## Стек

### Сервер
- .NET 8 LTS (до ноября 2026), ASP.NET Core Minimal APIs + Controllers
- EF Core 8 + Npgsql + PostgreSQL 16
- OpenIddict 5 (OAuth2/OIDC — password + refresh tokens)
- MediatR + FluentValidation (CQRS-lite)
- SignalR (real-time синхронизация)
- Hangfire (фоновые задачи)
- Serilog (структурированное логирование)

### Web
- React 18 + Vite + TypeScript
- shadcn/ui + Tailwind CSS
- TanStack Query + TanStack Table
- AG Grid Community (для тяжёлых grid'ов)
- Recharts / Tremor (графики)
- react-hook-form + Zod

### POS
- .NET 8 WPF, Windows 10+
- CommunityToolkit.Mvvm (source-generated MVVM)
- SQLite (локальная БД)
- Refit + Polly (API-клиент с retry)
- System.IO.Ports (драйверы весов: Масса-К и др.)

## Мультитенантность

Каждая сущность имеет `OrganizationId`. Пользователь scoped к организации. EF Core query filter автоматически изолирует данные между тенантами.

## Локальная разработка

```bash
# Поднять PostgreSQL
cd deploy && docker compose up -d

# Мигрировать БД
cd src/food-market.api && dotnet ef database update

# Запустить API
dotnet run --project src/food-market.api

# Запустить Web
cd src/food-market.web && pnpm install && pnpm dev
```

## Статус

🚧 Phase 0: фундамент (scaffolding, auth, multi-tenancy)
