8.6 KiB
Design: Доработка товара — удаление «под заказ», обязательные quantity и категория
Дата: 2026-05-15 Статус: На согласовании
Цель
Упростить модель товара: убрать концепцию «под заказ», сделать количество и категорию обязательными полями. Категория «Не указано» остаётся технической заглушкой для переноса товаров при удалении категории, но не видна в каталоге и не выбирается при редактировании.
Архитектура изменений
1. База данных (Prisma)
Миграция:
- Перед удалением полей: все товары с
inStock = falseполучаютquantity = 0 - Удалить поля
inStockиleadTimeDaysиз моделиProduct - Статус наличия определяется исключительно по
quantity:quantity > 0→ «В наличии»quantity = 0→ «Нет в наличии»
server/prisma/schema.prisma:
model Product {
// ... остальные поля без изменений ...
quantity Int @default(0)
// УДАЛЕНО: inStock Boolean @default(true)
// УДАЛЕНО: leadTimeDays Int?
category Category @relation(fields: [categoryId], references: [id], onDelete: Restrict)
categoryId String
// ...
}
2. Сервер — валидация и CRUD
server/src/routes/api/admin-products.js:
CREATE (POST):
quantity— required,Int >= 0(было nullable)categoryId— required (было: при пустом → авто-назначение «Не указано»)- Удалить валидацию
leadTimeDaysпри!inStock - Удалить принудительную установку
quantity = 1для «под заказ» - Вернуть 400:
'Укажите категорию'еслиcategoryIdотсутствует
UPDATE (PATCH):
quantity— required,Int >= 0(было nullable)categoryId— required (было: при пустом → «Не указано»)- Удалить логику очистки
leadTimeDaysприinStock = true - Удалить принудительную установку
quantity = 1 - Вернуть 400 при отсутствии
categoryId
JSON Schema:
CREATE_PRODUCT_SCHEMA: убратьleadTimeDays, сделатьquantityrequired (убратьnullable)PATCH_PRODUCT_SCHEMA: убратьleadTimeDays,quantity— если передан, то>= 0
server/src/routes/api/public-catalog.js:
- Удалить ветку
availability === 'in_stock'иavailability === 'made_to_order' - Фильтрация «в наличии» больше не нужна — все товары в каталоге
3. Клиент — админка (две страницы)
client/src/pages/admin/ui/AdminPage.tsx и client/src/pages/admin-products/ui/AdminProductsPage.tsx:
FormState:
- Удалить
inStock: booleanиleadTimeDays: string quantity: string— без nullable-семантики
UI:
- Удалить Switch «В наличии / Под заказ»
- Удалить TextField «Срок исполнения, дней»
- TextField «Количество»:
- Без helper «Оставьте пустым...»
- Новый helper: «0 = нет в наличии»
- Валидация: не может быть пустым,
parseInt >= 0
- Select «Категория»:
- Удалить
<MenuItem value="">с «Не указано» - Валидация: не даёт сохранить без выбранной категории
- Показать ошибку при попытке сохранить без категории
- Удалить
Submit-валидация:
- Удалить проверку
leadTimeDaysпри!inStock - Добавить проверку:
categoryIdне пустой → blocking error - Добавить проверку:
quantityне пустой → blocking error
4. Клиент — каталог
client/src/entities/product/ui/ProductCard.tsx:
- Удалить логику
'Под заказ · {leadTimeDays} дн.' - Новый статус:
quantity > 0→ «В наличии» (зелёный)quantity === 0→ «Нет в наличии» (серый/red)
client/src/pages/product/ui/ProductPage.tsx:
- Удалить chip
'Под заказ · {leadTimeDays} дн.' - Удалить alert
'Этот товар изготавливается под заказ...' - Статус определяется по
quantity
client/src/pages/checkout/ui/CheckoutPage.tsx:
- Удалить определение made-to-order товаров в корзине
- Удалить info alert о доставке после изготовления
5. Клиент — фильтры
client/src/pages/home/lib/use-product-filters.ts:
- Удалить
availability: 'all' | 'in_stock' | 'made_to_order'из state - Удалить
availabilityиз параметровfetchPublicProducts()
client/src/pages/home/ui/ProductFilters.tsx:
- Удалить
ToggleButtonGroupс'all','in_stock','made_to_order' - Удалить отображение категории «Не указано» из списка чипов (фильтр
cat.slug !== 'ne-ukazano')
6. Категория «Не указано» — что остаётся
| Где | Что происходит |
|---|---|
server/src/lib/default-category.js |
Остаётся — функция getOrCreateUnspecifiedCategory() |
server/src/index.js |
Остаётся — вызов при старте |
server/src/routes/api/admin-categories.js |
Остаётся — нельзя удалить/переименовать; при удалении категории товары переезжают в «Не указано» |
| Админка категорий | Остаётся — кнопка удаления заблокирована |
| Фильтры каталога | Скрыта — не показывается в чипах |
| Форма товара | Скрыта — не выбирается в Select |
Статус товара — новая логика
quantity > 0 → «В наличии» (зелёный chip/badge)
quantity = 0 → «Нет в наличии» (серый chip/badge)
Никаких других статусов. Поле inStock больше не существует.
Файлы для изменения
Сервер
| Файл | Изменения |
|---|---|
server/prisma/schema.prisma |
Удалить inStock, leadTimeDays |
server/src/routes/api/admin-products.js |
Валидация, schema, убрать логику под заказ |
server/src/routes/api/public-catalog.js |
Убрать фильтр availability |
Клиент
| Файл | Изменения |
|---|---|
client/src/pages/admin/ui/AdminPage.tsx |
FormState, UI, валидация |
client/src/pages/admin-products/ui/AdminProductsPage.tsx |
FormState, UI, валидация |
client/src/entities/product/ui/ProductCard.tsx |
Статус по quantity |
client/src/pages/product/ui/ProductPage.tsx |
Убрать под заказ UI |
client/src/pages/checkout/ui/CheckoutPage.tsx |
Убрать made-to-order detection |
client/src/pages/home/ui/ProductFilters.tsx |
Убрать availability toggle, скрыть «Не указано» |
client/src/pages/home/lib/use-product-filters.ts |
Убрать availability |
Миграция данных
// В Prisma migration:
// 1. UPDATE Product SET quantity = 0 WHERE inStock = false
// 2. ALTER TABLE Product DROP COLUMN inStock
// 3. ALTER TABLE Product DROP COLUMN leadTimeDays
Тестирование
Сервер:
- CREATE без categoryId → 400
- CREATE без quantity → 400
- CREATE с quantity = 0 → OK
- PATCH без categoryId → 400
- PATCH с quantity = 0 → OK
Клиент:
- Форма не сохраняется без категории
- Форма не сохраняется без количества
- Фильтры не содержат «Под заказ» и «Не указано»
- Карточка товара показывает «Нет в наличии» при quantity = 0