Commit graph

9 commits

Author SHA1 Message Date
nurdotnet 25f25f9171 phase1e: MoySklad import integration (admin-only, per-request token, no persistence)
Infrastructure (foodmarket.Infrastructure.Integrations.MoySklad):
- MoySkladDtos: minimal shapes of products, folders, uom, prices, barcodes from JSON-API 1.2
- MoySkladClient: HttpClient wrapper with Bearer auth per call
  - WhoAmIAsync (GET entity/organization) for connection test
  - StreamProductsAsync (paginated 1000/page, IAsyncEnumerable)
  - GetAllFoldersAsync (all product folders in one go)
- MoySkladImportService: orchestrates the full import
  - Creates missing product folders with Path preserved
  - Maps MoySklad VAT percent → local VatRate (fallback to default)
  - Maps barcodes: ean13/ean8/code128/gtin/upca/upce → our BarcodeType enum
  - Extracts retail price from salePrices (prefers "Розничная"), divides kopeck→major
  - Extracts buyPrice → PurchasePrice
  - Skips existing products by article OR primary barcode (unless overwrite flag set)
  - Batch SaveChanges every 500 items to keep EF tracker light
  - Returns counts + per-item error list

API: POST /api/admin/moysklad/test  — returns org name if token valid
API: POST /api/admin/moysklad/import-products { token, overwriteExisting }
  — Authorize(Roles = "Admin,SuperAdmin")

Web: /admin/import/moysklad page
- Amber notice: token is not persisted (request-scope only), how to create
  a service token in moysklad.ru with read-only rights
- Test connection button + result banner
- Import button with "overwrite existing" checkbox
- Result panel with 4 counters + collapsible error list

Sidebar adds "Импорт" section with MoySklad link.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 21:07:58 +05:00
nurdotnet 5af8f74b5e feat(web): rebrand to FOOD MARKET green (#00B207) per mobile app logo
- Extract brand colors from food-market-app/.../AppIcon/appicon.svg
  (background #00B207, white FOOD, pale-green E8F5E9 MARKET)
- Add @theme custom colors in index.css:
  --color-brand #00B207, --color-brand-hover #009305, --color-brand-dark #007605,
  --color-brand-light #E8F5E9, --color-brand-tint #D7F2D9, --color-brand-foreground #FFFFFF
- Replace all violet-* Tailwind classes with var(--color-brand*) in:
  LoginPage, Button, Field (input+checkbox), SearchBar, AppLayout (nav active state)
- New Logo component: FM square badge + "FOOD" + "MARKET" typography in brand colors
- Put Logo in sidebar header and on LoginPage
- Replace Vite default favicon with branded SVG (green square + FOOD MARKET)
- Page title "FOOD MARKET", theme-color meta tag for mobile browsers

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 20:53:42 +05:00
nurdotnet 1b2b5393fa phase1d: demo catalog seeder (35 products, 8 groups, 2 suppliers) + product edit form
Starter experience so the system is usable immediately after git clone → migrate → run.

DemoCatalogSeeder (Development only, runs once — skips if tenant has any products):
- 8 product groups: Напитки (Безалкогольные, Алкогольные), Молочка, Хлеб, Кондитерские,
  Бакалея, Снеки — hierarchical Path computed
- 2 demo suppliers: ТОО «Продтрейд» (legal entity, KZ BIN, bank details), ИП Иванов (individual)
- 35 realistic KZ-market products with:
  - Demo barcodes in 2xxx internal range (won't collide with real products)
  - Retail price + purchase price at 72% of retail
  - Country of origin (KZ / RU)
  - Хлеб marked as 0% VAT (socially important goods in KZ)
  - Сыр «Российский» marked as весовой
  - Articles in kebab-case: DR-SOD-001, DAI-MLK-002, SW-CHO-001 etc.

Product form (full page /catalog/products/new and /:id, not modal):
- 5 sections: Основное / Классификация / Остатки и закупка / Цены / Штрихкоды
- Dropdowns for unit, VAT, group, country, supplier, currency via useLookups hooks
- Defaults pre-filled for new product (default VAT, base unit, KZT)
- Prices table: add/remove rows, pick price type + amount + currency
- Barcodes table: EAN-13/8/CODE128/UPC options, "primary" enforces single
- Server-side atomic save (existing Prices+Barcodes replaced on PUT)

Products page: row click → edit page, Add button → new page.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 20:38:23 +05:00
nurdotnet 26d529b09b fix(web): remove TanStack devtools palm icon; restore user profile on dashboard
- Drop ReactQueryDevtools floating button (the "palm tree" in corner)
- Dashboard now shows: greeting with user name, stat cards, user profile
  (name/email/roles/orgId), and roadmap
- Add amber banner when API calls fail (typical cause: API not restarted
  after pulling new catalog code) with explicit fix instructions

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 20:33:10 +05:00
nurdotnet b6eefd3437 phase1c: web UI — sidebar layout + list/form pages for catalog
Shared components:
- AppLayout with grouped sidebar nav (Главное / Каталог / Контрагенты / Склады / Справочники)
- DataTable, Pagination, SearchBar, Button, Modal, Field (TextInput/TextArea/Select/Checkbox)
- PageHeader, useCatalogList + useCatalogMutations hooks (TanStack Query)
- types.ts with enums as const objects (erasableSyntaxOnly-compatible)

Dashboard: 4 stat cards (products/counterparties/stores/retail-points counts) + roadmap

List + edit-in-modal for 9 entities:
- Countries, Currencies (read-only)
- VatRates, UnitsOfMeasure, PriceTypes, Stores, RetailPoints, ProductGroups, Counterparties (full CRUD)
- Products: list + filters; full form deferred to next commit

All pages: search, pagination, row-click → modal edit, create button, delete with confirm.
Counterparty form uses Country lookup; RetailPoint form uses Store lookup.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 19:28:26 +05:00
nurdotnet 6b86106937 phase1b: catalog CRUD API (countries, currencies, vat, units, stores, retail points, product groups, counterparties, products)
Application layer:
- PagedRequest/PagedResult<T> with sane defaults (pageSize 50, max 500)
- CatalogDtos: read DTOs with joined names + input DTOs for upsert
- Product input supports nested Prices[] and Barcodes[] for atomic save

API controllers (api/catalog/…):
- countries, currencies (global, write requires SuperAdmin)
- vat-rates, units-of-measure, price-types, stores (write: Admin/Manager)
- retail-points (references Store, Admin/Manager write)
- product-groups: hierarchy with auto-computed Path, delete guarded against children/products
- counterparties: filter by kind (Supplier/Customer/Both), full join with Country
- products: includes joined lookups, filter by group/isService/isWeighed/isActive,
  search by name/article/barcode, write replaces Prices+Barcodes atomically

Role semantics:
- SuperAdmin: mutates global references only
- Admin: mutates/deletes tenant references
- Manager: mutates tenant references (no delete on some)
- Storekeeper: can manage counterparties and products (but not delete)

All endpoints guarded by [Authorize]. Multi-tenant isolation via EF query filter.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 19:22:56 +05:00
nurdotnet cb66684134 phase1a: catalog domain (countries, currencies, vat, units, counterparties, stores, retail points, products)
Domain (foodmarket.Domain.Catalog):
- Global references: Country (ISO-2), Currency (ISO-3 + symbol + minor unit)
- Tenant references: VatRate (Percent + IncludedInPrice + IsDefault), UnitOfMeasure (ОКЕИ code + DecimalPlaces)
- Counterparty: kind (Supplier/Customer/Both), type (Legal/Individual), BIN/IIN/TaxNumber, bank details
- Store + RetailPoint with fiscal placeholders
- ProductGroup: hierarchy via ParentId + denormalized Path
- PriceType (Розничная/Оптовая), Product (article, VAT, group, supplier, flags IsService/IsWeighed/IsAlcohol/IsMarked, min/max stock)
- ProductPrice (composite unique product+priceType), ProductBarcode (EAN13/EAN8/CODE128/UPC), ProductImage

Infrastructure:
- CatalogConfigurations with fluent API (indexes, precision 18/4 for money, FK with Restrict)
- 13 new DbSets on AppDbContext + builder.ConfigureCatalog()
- Migration Phase1Catalog — adds countries, currencies, vat_rates, units_of_measure, counterparties, stores, retail_points, product_groups, price_types, products, product_prices, product_barcodes, product_images

Seeders:
- SystemReferenceSeeder (always): 12 countries (KZ, RU, CN, TR, …), 5 currencies (KZT primary, RUB, USD, EUR, CNY)
- DevDataSeeder extended: for Demo Market seeds VAT (0%, 12% default+included), units (шт/кг/л/м/уп), price types (Розничная default, Оптовая), main store, POS-1

Total DB schema: 26 tables.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 19:16:10 +05:00
nns 047cf841f2 fix: pin API dev port to 5081 (match Vite proxy config)
Default launchSettings.json from `dotnet new web` picked random port 5039,
which doesn't match the Vite proxy target http://localhost:5081, so the
React app can't reach /connect/token during login.

- Fix http profile to 5081 (HTTPS to 5443)
- Remove IIS Express profile (Mac-only dev, not needed)
- Disable launchBrowser (we run Web separately)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 15:37:05 +05:00
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