# 10. Домен товаров

## Назначение
Товарный домен определяет контракт карточки товара, листингов, ценовых и складских атрибутов.

## Поведение системы
- Товары загружаются по API для листинга, карточки и связанных коллекций.
- Frontend отображает только те поля, которые есть в контракте.
- Бизнес-правила доступности товара приходят из backend.

## Обязательные JSON-свойства товара
- itemID
- name
- price
- currency
- categoryID
- visible

## Опциональные свойства
- discount
- images
- badges
- simpleDescription
- attributes
- stockStatus
- rating
- media
- specificationGroups
- variantOptions
- relatedCollections

## Product Engagement Models
- RatingSummary
  - average: number
  - totalReviews: number
  - distribution: [{ stars, count, share }]
- Review
  - id, rating, title, text, author, anonymous, verifiedPurchase, createdAt
  - likes/dislikes placeholders
  - photos: string[] (reserved for future uploads)
- Question
  - id, text, author, createdAt, likes, dislikes
  - answers: Answer[]
- Answer
  - id, text, author, createdAt
  - isOfficialSeller, isAccepted

## Product Experience 2.0 Optional Contracts

- media: `[{ type, url, thumbnailUrl?, alt?, title?, labels? }]`
  - type: `image | video | pdf | manual | warranty`
  - frontend renderer picks viewer by `type`
- specificationGroups: `[{ key, label?, labels?, attributes: [{ key, value, label?, labels?, unit? }] }]`
  - supports grouped specifications and translated labels
- variantOptions: `[{ key, label?, labels?, options: [{ value, label?, labels?, available? }] }]`
  - supports arbitrary variant groups (`color`, `size`, `storage`, etc.)
- relatedCollections: `[{ id, title, titles?, products: number[] }]`
  - supports multiple related collections from backend

## Product Page Config Extensions

`productPage` optional config additions:

- reviews.mode: `pages | load-more`
- questions.allowSubmission: `boolean`
- actions: `{ enabled, addToCart, buyNow, wishlist, compare, share, notifyMe }`

## Строгие правила
- Цена и валюта должны передаваться как валидная пара.
- Скрытые товары не участвуют в публичных витринах.
- categoryID должен ссылаться на существующую категорию.
- Виджет не изменяет товарные данные, только отображает.
- Frontend feature-слой работает только через ProductFacade.
- DTO/API shape не импортируется в feature components.
- reviews/questions не хранятся в bootstrap, только их feature-конфиг.

## Пример JSON товара
```json
{
  "itemID": 7812,
  "name": "Laptop Pro 14",
  "price": 129990,
  "currency": "RUB",
  "categoryID": 55,
  "visible": true,
  "discount": 10,
  "images": [
    { "url": "https://cdn.example.com/items/7812/main.jpg", "isMain": true }
  ],
  "badges": ["featured", "new"],
  "media": [
    { "type": "image", "url": "https://cdn.example.com/items/7812/main.jpg" },
    { "type": "video", "url": "https://cdn.example.com/items/7812/demo.mp4" },
    { "type": "pdf", "url": "https://cdn.example.com/items/7812/spec.pdf" }
  ],
  "specificationGroups": [
    {
      "key": "display",
      "labels": { "en": "Display", "ru": "Экран" },
      "attributes": [
        { "key": "size", "value": "14", "unit": "inch" },
        { "key": "resolution", "value": "2880x1800" }
      ]
    }
  ],
  "variantOptions": [
    {
      "key": "storage",
      "options": [{ "value": "256GB" }, { "value": "512GB" }]
    }
  ],
  "relatedCollections": [
    {
      "id": "similar-products",
      "title": "Похожие товары",
      "products": [9030, 9031]
    }
  ]
}
```

## Ответственность Frontend
- Показывать корректную цену, скидку, бейджи и доступность.
- Поддерживать переход из листинга в карточку товара.
- Учитывать locale/currency из tenant-конфигурации.

## Ответственность Backend
- Возвращать актуальные цены и доступность.
- Стабильно поддерживать идентификаторы товаров.
- Предоставлять медиа и атрибуты в согласованном формате.
- Поддерживать обратную совместимость: новые поля опциональны, старые payload остаются валидными.
