Przejdź do głównej zawartości

catalog

Katalog produktów: Products, ProductVariants, Categories, ProductAttributes i SalesChannels. Posiada wszystkie ścieżki odczytu, od których zależy storefront, oraz powierzchnię autorską po stronie admina.

Publiczne API​

Trasy admina są chronione przez catalog:read (list / get) / catalog:write (mutacje).

Verb + PathOdbiorcaCel
GET /api/v1/catalog/productsstorefront / API keyLista/szukaj/filtruj produkty w aktywnym Sales Channel
GET /api/v1/catalog/products/:idOrSlugstorefrontSzczegóły produktu (cena pominięta na niepublicznych Sales Channels)
GET /api/v1/catalog/categoriesstorefrontZagnieżdżone drzewo kategorii
GET /api/v1/catalog/filtersstorefrontAtrybuty filtrowalne dla aktywnego Sales Channel
GET /api/v1/catalog/sitemap.xmlcrawlersMapa witryny SEO
GET /api/v1/admin/catalog/products?includeArchivedadminLista produktów admin (z draftami; wiersze zarchiwizowane opt-in)
GET /api/v1/admin/catalog/products/:idadminSzczegóły produktu
POST /api/v1/admin/catalog/productsadminUtworzenie produktu (type niemutowalne po utworzeniu; sku edytowalne)
PATCH /api/v1/admin/catalog/products/:idadminAktualizacja (łącznie z sku); zapisuje wiersz audytu ze stateBefore / stateAfter; odmawia z 409 sku_in_use, gdy nowe SKU należy już do innego produktu
DELETE /api/v1/admin/catalog/products/:idadminArchiwizacja (soft)
GET /api/v1/admin/catalog/attributesadminLista atrybutów
GET /api/v1/admin/catalog/attributes/by-flag?flag=isPromoRule|isComparable|...adminPayload pickera — każdy atrybut z żądaną flagą
GET /api/v1/admin/catalog/attributes/:idOrKeyadminOdczyt pojedynczego atrybutu
POST /api/v1/admin/catalog/attributesadminUtworzenie atrybutu (akceptuje nowe flagi + inline options[] dla typów select-style)
PATCH /api/v1/admin/catalog/attributes/:keyadminHot-toggle isFilterable / isSearchable / isVariantAxis / isPromoRule / isComparable / isVisibleOnProductPage / isRequired / filterPosition (re-emituje attribute.updated.v1)
DELETE /api/v1/admin/catalog/attributes/:idOrKeyadminUsunięcie; odmawia z 409 attribute_in_use_by_set, dopóki jakikolwiek Attribute Set nadal się odwołuje
GET /api/v1/admin/catalog/attributes/:idOrKey/optionsadminLista wierszy opcji dla atrybutów select/enum/multiselect
POST /api/v1/admin/catalog/attributes/:idOrKey/optionsadminDołączenie opcji
PATCH /api/v1/admin/catalog/attribute-options/:optionIdadminPatch label / labelDefault / isDefault / sortOrder (option value niemutowalne)
DELETE /api/v1/admin/catalog/attribute-options/:optionIdadminUsunięcie; odmawia z 409 option_in_use, dopóki jakikolwiek produkt niesie wartość
POST /api/v1/admin/catalog/attribute-set-previewadminPodgląd, które atrybuty Set będą edytowane / ukryte, gdy operator przełączy Attribute Set produktu
GET /api/v1/admin/catalog/categoriesadminPłaska lista, UI składa w drzewo
POST /api/v1/admin/catalog/categoriesadminUtworzenie (rodzic musi istnieć)
PATCH /api/v1/admin/catalog/categories/:idadminAktualizacja; reparenting przechodzi łańcuch nowego rodzica, żeby odmówić cykli (409)
DELETE /api/v1/admin/catalog/categories/:idadminSoft-delete; odrzuca z 409, gdy aktywne dziecko nadal odwołuje się do wiersza
PUT /api/v1/catalog/products/by-sku/:skuAPI keyIdempotentny upsert (sync PIM)

Encje​

Product, ProductVariant, Category, ProductAttribute, SalesChannel, plus mosty M:N product_categories, sales_channel_products, product_assets.

Emitowane zdarzenia​

product.created.v1, product.updated.v1, product.archived.v1, attribute.updated.v1. Konsumowane przez indeksator wyszukiwania i bridgowane do subskrybentów webhook.

Punkty rozszerzenia​

  • Ceny per Sales Channel — serwis query dostaje kontekst SalesChannel; nowe gating (np. katalogi per segment klienta) dodajesz przez kompozycję w catalog-query.service.ts.
  • Unikalność slug — slug jest unikalny we wszystkich Sales Channels domyślnie; nadpisz slugifier w catalog-admin.service.ts, jeśli kolizje locale staną się problemem.

Powierzchnie struktury i kompozycji produktu​

Katalog urósł o kilka powierzchni capability, każda ma własną stronę:

  • Zestawy atrybutów — wielokrotnie używane schematy atrybutów przypięte do Products, z systemowym Default
  • Galeria produktu — galeria obrazu / wideo z invariantami etykiet Base / Small / Thumbnail egzekwowanymi na poziomie bazy
  • Załączniki — pliki do pobrania (certyfikaty, specyfikacje techniczne, ...) ze słownikiem typów
  • Powiązania produktów — Related, Up-sell, Cross-sell napędzające cross-merchandising na PDP i w koszyku
  • Produkty złożone — grouped (stałe dzieci), bundle (konfigurowalne sloty), virtual (dostawa cyfrowa)

Obsługiwanych jest teraz pięć typów produktu: simple, configurable, grouped, bundle, virtual. simple i configurable to pierwotna para; pozostałe trzy dodano później.

Rozszerzenia atrybutów na ścieżkach odczytu Catalog​

Prace nad atrybutami dodały powierzchnię operacyjną, której storefront potrzebuje do renderowania bogatych informacji o produkcie, a moduły search / promotions potrzebują do rozwiązywania zapytań klientów. Dedykowana strona Atrybuty opisuje w pełni powierzchnię autorską atrybutów — ta sekcja tylko podsumowuje, co zmieniło się na ścieżkach odczytu Catalog.

Nowe flagi atrybutów​

ProductAttribute dostaje cztery flagi behawioralne + pozycję numeryczną + fallback etykiety per locale:

  • isPromoRule (boolean) — kwalifikacja pickera dla wariantu kryterium attribute edytora Promotion Rule
  • isVisibleOnProductPage (boolean) — pokaż atrybut na zakładce storefront PDP „Parametry produktu”, gdy produkt niesie wartość
  • isRequired (boolean) — egzekwowane przy zapisie produktu, gdy atrybut jest częścią Attribute Set produktu
  • filterPosition (number) — klucz sortowania sidebar filtrów storefront (niższe wcześniej; remisy łamane etykietą)
  • labelDefault (string) — fallback, gdy aktywny locale nie ma pasującego klucza w per-locale JSONB label

Listy opcji​

Typy atrybutów select-style (select, enum, multiselect) niosą uporządkowaną listę opcji — każdy wiersz kluczowany przez (definition, value) z per-locale label + fallback + sort order + flagą default. Legacy kolumna enum_values: string[] JSONB na product_attributes została wycofana migracją 032 (do własnościowej tabeli katalogu attribute_options), a migracja 102 przeniosła wiersze do generycznej tabeli custom_field_options. Istniejący czytelnicy projektują listę opcji z powrotem w legacy formę dla kompatybilności wstecznej na granicy API.

Edytowalne SKU​

sku produktu jest mutowalne. Wewnętrzne kanoniczne odwołanie dla każdego linku cross-module (assets, links, pozycje RFQ, ...) to UUID Product.id, który nigdy się nie zmienia. Aktualizacja SKU zapisuje wiersz audytu i odmawia z 409 sku_in_use, gdy nowa wartość należy już do innego produktu.

Zamiana Attribute Set​

Gdy operator przypisze inny Attribute Set do Product, formularz admina re-renderuje się, pokazując tylko atrybuty nowego Set. Wartości atrybutów poza nowym Set pozostają w kolumnie JSONB po stronie serwera — powrót do poprzedniego zestawu je z powrotem eksponuje. Endpoint attribute-set-preview pozwala edytorowi ostrzec operatora, które pola zostaną ukryte vs. zachowane, zanim potwierdzi.

Powierzchnia odczytu cross-module​

Dwie metody na CatalogQueryService przekraczają granice modułów (udokumentowane porty serwisowe):

  • comparableAttributeKeys(): string[] — Compare
  • promoRuleAttributeKeys(): string[] + getAttributeWithOptions(key) — Promotions
  • buildVisibleAttributesProjection() — wewnętrzne, używane przez odpowiedź szczegółów PDP do złożenia payloadu visibleAttributes[]

Atrybuty jako rozszerzenia Custom Field​

Magazyn definicji atrybutów zbiegł się z generyczną warstwą Custom Fields, którą posiada moduł custom_fields, w kształcie adaptera, a nie przepisania. Na powierzchni HTTP nic się nie zmieniło — każdy endpoint powyżej zachowuje kształt — ale model magazynowania i własności jest inny:

  • Atrybut produktu to rozszerzenie katalogu definicji Custom Field hosta produktu. Generyczna tożsamość (key, per-locale label + labelDefault, valueType, required) żyje na wierszu custom_field_definitions z entity_type = 'product'. Tabela product_attributes pozostaje, przebudowana jako cienki wiersz rozszerzenia 1:1 (custom_field_definition_id UNIQUE FK) niosący tylko flagi behawioralne katalogu (isSearchable, isFilterable, isVariantAxis, displayAsSlider, isComparable, quickSearchable, isPromoRule, filterPosition, isVisibleOnProductPage, channelScoped, languageScoped, massEditable) plus dwa refinements prezentacji (selectDisplay, numericKind), które zachowują bezstratnie legacy rozróżnienia enum/select i number/price. Flagi pozostają własnością katalogu — generyczny core nigdy ich nie interpretuje.
  • Opcje żyją w custom_field_options. Własnościowa tabela katalogu attribute_options zniknęła; listy opcji to zwykłe wiersze opcji Custom Field na definicji hosta produktu.
  • Jedna powierzchnia zapisu: /catalog/attributes. Mutacje atrybutów i opcji to Commands katalogu tworzące/aktualizujące/usuwające definicję i rozszerzenie razem w jednej transakcji (jeden wiersz audytu), używając transakcyjnego apply seam eksportowanego przez custom_fields. Generyczna powierzchnia admin Custom Fields listuje definicje produktów read-only i odmawia mutacji z 409 host_managed.
  • Migracja 102_attributes_on_custom_fields.ts wykonała jednorazową konwergencję w jednej transakcji: backfill jednej definicji per legacy atrybut (key, labels, zmapowany value type, required, deterministyczny sort order), przeniosła wiersze attribute_options do custom_field_options, re-keyowała attribute_set_attributes na id definicji, dodała custom_field_definition_id / select_display / numeric_kind do product_attributes, usunęła zduplikowane kolumny (key, label, label_default, value_type, is_required) i usunęła attribute_options. Migracja jest odwracalna (down() przywraca legacy kształt) i abortuje głośno przy kolizji reserved-key.
  • Wartości atrybutów się nie przeniosły — products.attribute_values, product_variants.variant_attribute_values i product_value_overrides zachowują kształt i własność katalogu (host posiada swoje dane).

Wewnętrzni konsumenci (search, quick order, comparisons, bulk edit, port promotions, edytor scope) czytają atrybuty przez eksportowany przez katalog CatalogAttributeReadService, który składa definicję i rozszerzenie w legacy-shaped CatalogAttributeView.