Zákazník si srdíčkem uloží produkt a hvězdičkou označí kategorii. Když oblíbený produkt zlevní nebo se naskladní, nebo když ve sledované kategorii přibude produkt, který smí vidět, dostane jednou denně e‑mail. Co chce dostávat, si nastaví v účtu.
Klient položku schválil slovy „toto určitě". Kalkulace slibuje i upozornění, ale zná jen oblíbené produkty. Bez sledování kategorie nejde upozornit na nový produkt, a bez doručovacího kanálu nemají upozornění kde být. Rozhodnuto 23. 9. 2026: kanál je e‑mail, jako u ostatních upozornění. Notifikační centrum v e‑shopu se nestaví.
Kam patří. Jádro MasterShopu (větev front-api): oblíbené nad existujícím modulem Wishlist a sledované kategorie, šest endpointů. Hodí se každému klientovi na headlessu. Obálka: upozornění e‑mailem: nastavení v účtu, denní úloha, šablona souhrnu. Typy upozornění a faktura po splatnosti z AlbiLine jsou šité na ALBI. Obrazovky v SFX. Názvy nových tabulek a endpointů jsou pracovní, v jádru je pojmenuje programátor.
Oblíbené a sledování jdou stavět hned. Upozornění potřebují rozhodnutí D3 o tom, co je „nový produkt", než se napíše denní úloha.
| # | Otázka a náš návrh |
|---|---|
| K1 | Jsou oblíbené a sledované kategorie per účet, nebo sdílené v rámci firmy? Návrh: per účet. Podúčty jsou různí lidé s různou prací. Sdílení je snadné doplnit později, opačně to nejde. |
| K2 | Má se upozornění na fakturu po splatnosti posílat všem účtům firmy, nebo jen hlavnímu účtu? Návrh: jen hlavnímu účtu, ostatním jen když si to zapnou. |
| K3 | V kolik hodin má denní souhrn chodit? Návrh: 6:00 místního času. |
| # | Otázka |
|---|---|
| D1 | Oblíbené stojí na jádrové tabulce wishlist_items (zákazník, produkt, datum přidání). Její pojmenované seznamy (wishlist_categories) a sdílení se v B2B NEPOUŽÍVAJÍ, položky mají seznam prázdný. Jak pojmenovat nové endpointy jádra a do které skupiny FrontAPI je zařadit, rozhodne programátor. Názvy níže jsou pracovní. |
| D2 | Jádro má Watchdog na naskladnění produktu (tabulka watchdog, FrontAPI i SFX stránka, cron po 15 minutách, jeden e‑mail na záznam). Přes FrontAPI dnes umí jen typ naskladnění. Navrhujeme ho v B2B nepoužít a naskladnění oblíbeného řešit v denním souhrnu. Má se Watchdog na B2B prezentacích vypnout? |
| D3 | „Nový produkt v kategorii" = produkt s datem přidání po posledním běhu úlohy, který je pro zákazníka viditelný. Produkt, který zákazníkovi přibyl do sortimentu později (nový řádek v povoleném výpisu), se tím NEZACHYTÍ. Zápis povoleného výpisu ze synchronizace nemá událost. Stačí to pro fázi 1, nebo se má porovnávat i změna výpisu? |
| D4 | Zlevnění: cena produktu pro zákazníka je z ceníku adresy. Denní úloha porovná uloženou cenu u oblíbeného záznamu s aktuální. Sklad má observer bez události, cena má událost productBasePriceObject.afterSave. Polling v denní úloze je pro obojí jednodušší. Souhlas? |
| D5 | Crontab je v samostatném repu mimo workspace. Kdo tam denní úlohu založí? |
Jedna existující a jedna nová tabulka v jádru, tři nové tabulky v obálce backendu (albi-b2b-backend). Jádro neví nic o upozorněních, obálka čte jeho tabulky.
| Tabulka | Sloupce | Poznámka |
|---|---|---|
wishlist_items · jádro, existuje | wishlist_item_id, customer_id, product_id, wishlist_category_id (v B2B vždy NULL), add_time | Unikát (zákazník, produkt, seznam). Modul Wishlist, migrace existuje. Struktura se NEMĚNÍ. D1 |
customer_watched_categories · jádro, nová | id, customer_id, category_id, add_time | Unikát (zákazník, kategorie). Sleduje se i podstrom, ten se počítá při běhu úlohy, neukládá se. Název tabulky je pracovní. |
b2b_favourite_watch_state · obálka | customer_id, product_id, last_price (cena bez DPH pro zákazníka při posledním běhu úlohy), last_in_stock (0/1), last_checked_at | Stav pro upozornění k oblíbeným. Plní jen denní úloha. Chybějící řádek úloha založí bez události, takže nový oblíbený produkt nevyvolá falešné „zlevnilo". |
b2b_customer_notification_settings · obálka | customer_id, type (price_drop · back_in_stock · new_in_category · invoice_overdue), enabled (0/1), update_time | Chybějící řádek = výchozí hodnota podle typu (sekce 05). Jádrová tabulka zákazníka nemá kam preference uložit, samostatná tabulka neexistuje. |
b2b_notification_events · obálka | id, customer_id, type, product_id (nebo NULL), category_id (nebo NULL), document_code (nebo NULL), payload (JSON: stará a nová cena, název), created_at, sent_at (NULL = neodesláno) | Fronta pro denní souhrn. Po odeslání se řádky drží 90 dní pro dohledání, pak se mažou. |
POST /api-wishlist/products s id produktu. Srdíčko se vyplní hned, bez čekání na odpověď.
wishlist_items. Opakované přidání duplicitu NEVYTVOŘÍ.DELETE /api-wishlist/products/{productId}. Srdíčko se vyprázdní hned.GET /api-wishlist/products: produktové karty ve stejném formátu jako katalog. Produkt, který zákazník už nesmí vidět, v odpovědi NENÍ, ale záznam zůstane, aby se po vrácení do sortimentu objevil.POST /api-watched-categories/categories. Hláška: „Sledujete Hry a puzzle včetně podkategorií."DELETE /api-watched-categories/categories/{categoryId}).GET /api-b2b/notification-settings: čtyři přepínače.PUT /api-b2b/notification-settings s celým stavem. Uloží se hned.Oblíbené staví na jádrovém modulu Wishlist, vlastní tabulka oblíbených v obálce NEVZNIKÁ. Watchdog jádra se NEPOUŽÍVÁ (D2). Jádrová tabulka zákazníka se NEMĚNÍ.
Denní úloha v obálce backendu, vzor existující CLI úlohy v Local/crons/ se třídou dědící z EshopCLI, která sama řeší mutex a CronMonitor. Odesílá se přes mailSender() stejně, jak to dělá B2BNotificatorService v obálce albi.eu.
| Typ | Kdy vznikne událost | Výchozí | Komu |
|---|---|---|---|
price_drop | Cena oblíbeného produktu bez DPH podle ceníku doručovací adresy zákazníka je nižší než last_price v b2b_favourite_watch_state. | zapnuto | účet s oblíbeným |
back_in_stock | Oblíbený produkt měl last_in_stock = 0 a teď je skladem. | zapnuto | účet s oblíbeným |
new_in_category | Ve sledované kategorii nebo jejím podstromu je produkt s datem přidání po posledním běhu úlohy, viditelný pro zákazníka. D3 | zapnuto | účet se sledováním |
invoice_overdue | Faktura uzlu firmy přešla do stavu po splatnosti (ze synchronizace AlbiLine) a k ní ještě nevznikla událost. | zapnuto jen hlavní účet | hlavní účet K2 |
wishlist_items): načte aktuální cenu pro zákazníka (ceník jeho aktivní doručovací adresy) a skladovost, porovná se stavem v b2b_favourite_watch_state, založí události, uloží nové hodnoty a last_checked_at. Produkt bez stavu jen zapíše, událost NEZALOŽÍ. Pak sledované kategorie (jádrová customer_watched_categories): pro každý záznam najde nové viditelné produkty v podstromu. Pak faktury: nové stavy po splatnosti. D4sent_at = čas běhu a příznakem v payloadu, že byly potlačené. Neodejdou, ale je vidět, že nastaly.B2B_DAILY_DIGEST z tabulky šablon pro prezentaci zákazníka. Po odeslání se u událostí nastaví sent_at.
Dobrý den, za posledních 24 hodin se u vašich oblíbených produktů a sledovaných kategorií změnilo tohle.
Zlevnilo
Puzzle Karak 500 dílků · 139 → 129 Kč/ks bez DPH · Zobrazit
Nové v kategorii Hry a puzzle
Puzzle Karak Deluxe 1000 dílků · 219 Kč/ks · Zobrazit
Kvarteto Dinosauři · 59 Kč/ks · Zobrazit
Ceny platí pro vaši doručovací adresu Lípová 12. Nastavit, co chci dostávat.
Sekce „Zase skladem" a „Faktura po splatnosti" se v tomto příkladu vynechaly, protože nenastaly.
Podle prototypu: katalog (hvězdičky), karty a detail (srdíčko), stránka Oblíbené, Můj účet → Nastavení. Design system ALBI.
| Místo | Prvek a chování |
|---|---|
| Produktová karta | Srdíčko vpravo nahoře nad obrázkem. Prázdné / plné. Klik nepřechází na detail. SFX jádro má ikonu wishlistu jen v hlavičce, komponenta srdíčka vzniká v obálce. |
| Detail produktu | Tlačítko „Do oblíbených" / „V oblíbených" vedle množství. Pod ním věta „Dáme vědět e‑mailem, když zlevní nebo bude zase skladem." |
| Strom kategorií v katalogu | Hvězdička za názvem každé kategorie. Vyplněná = sledováno. U potomka sledovaného rodiče vyplněná a neaktivní s nápovědou. |
| Stránka Oblíbené (Můj účet) | Nahoře karty oblíbených produktů s tlačítkem Do košíku a srdíčkem k odebrání. Dole seznam sledovaných kategorií, u každé Přestat sledovat. Prázdné stavy: „Srdíčkem u produktu si ho uložíte." / „Hvězdičku najdete v katalogu." |
| Můj účet → Upozornění e‑mailem | Čtyři přepínače s popisem. Věta nahoře: „Upozornění chodí jednou denně e‑mailem na vaši adresu." Přepínač faktury vidí každý účet, výchozí stav podle role. |
| Nástěnka (F03) | Blok Oblíbené: až 4 karty a odkaz na stránku. |
| Oblíbený produkt zlevnil | zapnuto |
| Oblíbený produkt je zase skladem | zapnuto |
| Nový produkt ve sledované kategorii | zapnuto |
| Faktura po splatnosti | vypnuto |
Přepínače ukládají hned. U podúčtu je faktura ve výchozím stavu vypnutá, u hlavního účtu zapnutá.
Osm nových endpointů, všechny s JWT zákazníka. Šest v jádru MasterShopu (modul FrontApi), dva v obálce backendu ve skupině /api-b2b/. Názvy jsou pracovní. D1
| Endpoint | Stav | K čemu |
|---|---|---|
GET /api-wishlist/products | nový · jádro | Produktové karty oblíbených, jen viditelné. Parametr idsOnly=1 vrátí jen pole id produktů pro vyplnění srdíček v katalogu. |
POST /api-wishlist/products | nový · jádro | Tělo { "productId" }. Idempotentní: opakované volání nevytvoří duplicitu, vrátí 200. |
DELETE /api-wishlist/products/{productId} | nový · jádro | Odebere. Neexistující záznam → 204, ne chyba. |
GET /api-watched-categories/categories | nový · jádro | Seznam { categoryId, name, slug }. |
POST /api-watched-categories/categories | nový · jádro | Tělo { "categoryId" }. Kategorie, kterou zákazník nesmí vidět → 404. |
DELETE /api-watched-categories/categories/{categoryId} | nový · jádro | Odebere. |
GET /api-b2b/notification-settings | nový · obálka | Čtyři typy s hodnotou. Chybějící řádek vrátí výchozí hodnotu. |
PUT /api-b2b/notification-settings | nový · obálka | Tělo { "price_drop": true, "back_in_stock": true, "new_in_category": true, "invoice_overdue": false }. Ukládá celý stav. |
Jedna e‑mailová šablona ve stávajícím modulu šablon. Nic dalšího.
B2B_DAILY_DIGEST, jeden řádek pro každou ze čtyř prezentací. Texty sekcí a předmět jsou v šabloně, položky se dosazují proměnnými.customerName, deliveryAddressLabel, invoicesOverdue[], priceDrops[], backInStock[], newInCategories[] (kategorie s produkty), settingsUrl.Stávající obrazovka modulu šablon, přibývá jen nový kód šablony. Stejně vzniknou řádky pro SK, PL a EN.