Na kartě produktu tabulka: od 1 balení základní cena, od 6 balení nižší, od 12 ještě nižší. Košík počítá cenu podle množství. Pásma přicházejí z AlbiLine jako všechny ceny, e‑shop je ukládá k ceníku a neumožňuje je zadávat ručně.
Odběratel má vidět, kolik ušetří, když objedná víc. Ceníky ALBI dnes drží jednu cenu na ceník, produkt a měnu, bez vazby na množství. Množstevní sleva v jádře neexistuje, modul VolumeDiscounts je sleva podle hodnoty košíku, a stará B2B obálka slevy v košíku zakazuje natvrdo. Pásma jsou proto nová datová struktura na třech místech: v AlbiLine, v e‑shopu a na frontendu.
Kam patří. Jádro MasterShopu (větev front-api): tabulka pásem, výpočet ceny podle množství v košíku, pásma v datech produktu a košíku, náhled v administraci. Množstevní ceny jsou obecný B2B požadavek. Obálka: import pásem v modulu AL ze synchronizace AlbiLine, tabulka pásem na detailu a štítek v košíku v SFX. Názvy nových tabulek a endpointů jsou pracovní, v jádru je pojmenuje programátor.
K1 a K2 jsou obchodní pravidla, bez nich se nedá dokončit výpočet. K3 je závazek AlbiLine. Frontend a DTO jdou stavět hned.
| # | Otázka a náš návrh |
|---|---|
| K1 | Platí pásmo za položku, nebo za celou objednávku napříč produkty? Návrh: za položku. Je to jednoduché na pochopení i na výpočet a odpovídá tabulce na kartě produktu. |
| K2 | Počítají se pásma v baleních, nebo v kusech? Návrh: v baleních, protože B2B objednává po baleních a tabulka „od 6 balení" je čitelnější než „od 36 ks". |
| K3 | Dodá AlbiLine pásma novou tabulkou podle sekce 03? Bez toho funkce nemá data. Kdo a kdy na straně ALBI. |
| K4 | Modul množstevních slev je na dnešním B2B vypnutý natvrdo. Je to záměr, který má platit dál (žádné jiné slevy v B2B), nebo jen stav? |
| # | Otázka |
|---|---|
| D1 | Ceník z doručovací adresy načítá jen stará obálka. Jádro ani obálka albi.eu kontext z adresy neplní a albi.eu sloupec customers_addresses.pricelist_id záměrně nemá. Nová obálka musí tuhle vazbu přenést dřív, než mají pásma smysl. Patří to k přenosu stávajících funkcí (odhad, blok B), tady jen připomínka. |
| D2 | Výpočet ceny položky v košíku pro B2B ve FrontAPI dnes neexistuje (bloker Z1). Kam přesně pásma zapojit, se rozhodne s řešením blokeru. Navrhujeme override cenové služby v obálce, jako to dělá stará obálka pro násobení balením. |
| D3 | Velikost balení není v DTO produktu ani v DTO položky košíku. Přidat pole piecesInPackage do produktové karty přes override konvertoru v obálce. Potřebují to i F01 a F05. |
| D4 | V synchronizaci ceníkových cen je v cyklu podezřelý return místo continue. Ověřit před tím, než se na stejný kód navěsí import pásem. |
price_lists_products s klíčem ceník, produkt, měna, typ ceny (b2b), stát a jedinou cenou. Sloupec pro množství neexistuje.PriceList (kód, název, procento slevy, sleva z RRP) a ceníkové ceny tabulkou PriceListSpecialItem (kód ceníku, cost level, měna, cena). Produkt se váže přes CostLevelCode. Nic o množství.| Tabulka | Sloupce | Poznámka |
|---|---|---|
b2b_price_list_tiers | price_list_id, product_id, currency_code, min_packages (int, od kolika balení), price (bez DPH za kus), update_time | Unikát (ceník, produkt, měna, min_packages). Řádek pro min_packages = 1 se NEUKLÁDÁ, to je ceníková cena. |
Nová tabulka PriceListTier ve stejném duchu jako PriceListSpecialItem, aby import mohl použít stejné mapování produktu přes cost level.
| Pole | Význam |
|---|---|
PriceListCode | Kód ceníku, stejný jako v PriceList. |
CostLevelCode | Kód cenové hladiny produktu, stejný klíč jako u ceníkové ceny. |
CurrencyCode | Měna. |
MinPackages | Od kolika balení pásmo platí. Celé číslo větší než 1. |
Price | Cena za kus bez DPH v pásmu. |
PriceListSpecialItem se zpracuje PriceListTier stejným mapováním. Chybějící pásma pro kombinaci ceník + produkt znamenají smazání pásem v e‑shopu (plná synchronizace, ne přírůstková).q.q = 1.b2b_price_list_tiers pro daný ceník, produkt a měnu se vezme řádek s nejvyšším min_packages ≤ q.
q × balení). Bez DPH, DPH se přičítá až v souhrnu košíku podle sazby produktu.⚠️ Dev: výpočet ceny položky v košíku pro B2B zákazníka ve FrontAPI dnes končí výjimkou v jádře (bloker Z1). Pásma se zapojí do řešení blokeru, ne vedle něj. D2
Podle prototypu: detail produktu a košík. Design system ALBI.
| Místo | Prvek a chování |
|---|---|
| Detail produktu | Pod cenou tabulka „Cena podle množství": sloupce Od množství (bal.), Sleva (% proti základu, spočítané SFX), Cena za kus, Cena za balení. Řádek platného pásma je zvýrazněný a mění se při změně množství v poli. Pod tabulkou věta „Ceny bez DPH, pro vaši adresu Lípová 12". |
| Detail produktu bez pásem | Tabulka se NEVYKRESLÍ. Cena je jako dnes. |
| Výpis kategorie, karta | Pod cenou drobný text „od 6 bal. 123 Kč/ks", jen když produkt má pásma. Tabulka ve výpisu NENÍ. |
| Košík, položka | Cena za kus podle pásma. Štítek „−5 % od 6 bal." u položky v pásmu. Nápověda pod položkou: „Přidejte ještě 2 balení a cena klesne na 116 Kč/ks", jen když další pásmo existuje a chybí do něj nejvýše polovina jeho prahu. |
| Košík, souhrn | Beze změny. Součty jsou z cen položek. |
| Detail objednávky | Cena za kus uložená při odeslání. Štítek pásma se NEUKAZUJE, objednávka je historie. |
| Od množství | Sleva | Cena za kus | Cena za balení |
|---|---|---|---|
| 1 bal. | — | 129 Kč | 774 Kč |
| 6 bal. | −5 % | 123 Kč | 738 Kč |
| 12 bal. | −10 % | 116 Kč | 696 Kč |
Nová je tabulka a zvýraznění platného řádku. Procento slevy počítá SFX ze základu, backend posílá jen ceny.
Žádný nový endpoint. Rozšiřují se odpovědi existujících endpointů produktu a košíku přímo v jádru.
| Endpoint | Stav | Co se přidá |
|---|---|---|
Produktová karta a detail (GET /api-products/…) | rozšířit DTO | piecesInPackage (int) a price.tiers[]: { minPackages, minPieces, price, priceWithVat }, seřazeno od nejnižšího prahu, bez řádku pro 1 balení. Prázdné pole, když pásma nejsou. Ceny podle ceníku z hlavičky X-PB-Price-List-Id. D3 |
Košík (GET/PUT /api-carts/carts/{token}) | rozšířit DTO | U položky appliedTier { minPackages, price } nebo null, a nextTier { minPackages, price, packagesMissing } nebo null. Cena položky je podle pásma. Závisí na blokeru Z1. D2 |
| Detail objednávky | beze změny | Cena za kus je uložená při odeslání, pásmo se nepřenáší. |
"price": {
"priceWithoutVat": 129, "priceWithVat": 156.09, "currencyCode": "CZK", "priceListId": 7,
"tiers": [
{ "minPackages": 6, "minPieces": 36, "price": 123, "priceWithVat": 148.83 },
{ "minPackages": 12, "minPieces": 72, "price": 116, "priceWithVat": 140.36 }
]
},
"piecesInPackage": 6
recommendedPrice patří k přenosu stávajících funkcí, ne sem, ale sedí do stejného overridu konvertoru.Jen náhled, žádné zadávání. Zdrojem pravdy je AlbiLine.
/admint/pricelists.php, záložky Základní a Texty) se NEMĚNÍ.| Ceník | Měna | Cena bez DPH |
|---|---|---|
| Velkoobchod B | CZK | 129,00 |
| Velkoobchod C | CZK | 137,00 |
| Ceník | Měna | Od balení | Cena za kus | Synchronizace |
|---|---|---|---|---|
| Velkoobchod B | CZK | 6 | 123,00 | 25. 9. 2026 04:10 |
| Velkoobchod B | CZK | 12 | 116,00 | 25. 9. 2026 04:10 |
q je celé číslo. K2