Sdílené principy
DROP = systém kdy marketplace (Alza, Mall, …) přijme objednávku od zákazníka, ale fakturuje a expeduje Vapol. Apivapol funguje jako most mezi marketplace API a Karatem:
- Příjem objednávky — buď push (marketplace zavolá náš REST endpoint), nebo pull (apivapol periodicky polluje API).
- Lokální záznam — DB tabulky
api_{drop}_orders+ items + address. - Karat insert —
user_imp_w3_obj_h+user_imp_w3_obj_p(Doctrine entityW3ImpObjednavkaHlav). - Karat confirm — rezervace zboží + nastavení
user_typ_expedice = '{drop}-drop-0'(literál na který Karat reaguje, vizfeedback_preserve_sova_literals). - Marketplace confirm — vrátíme marketplace náš Karat doklad / shipment number.
- Tracking — sync status doručení (DPD, Ulozenka, …) zpět do marketplace.
- Billing — měsíční CSV exporty pro účtárny.
Karat literál Waitting for Confirm v poznámce (překlep tt záměrný — Karat na něj reaguje) drží objednávku ve stavu „čeká na potvrzení" do Confirm fáze.
Překlad chyb dopravců do CZ (create-shipment)
Skladníci při createShipment dostávali z API dopravců (DPD, PPL, GLS, Packeta, UPS,
FedEx, Geis, Messenger, InPost) chyby v angličtině a nerozuměli jim. CarrierErrorTranslator
je překládá do věcné české hlášky, aniž by měnil existující API kontrakt.
Fallback řetězec
- Static pattern (~0.1 ms, v PHP kódu) — 39 patternů napříč 9 dopravci v
Services/ErrorTranslation/Patterns/. - DB cache — tabulka
carrier_error_translation(PG),source = 'ai' | 'manual', hash normalizuje dynamické části (UUID, ID, timestampy). - AI (Google Gemini) — jen když
allowAi = true(pouzecreateShipmentakce) a rate limit OK; výsledek se uloží do cache. - Raw fallback — když vše selže, vrátí se originál s prefixem dopravce + Tracy log.
Odpověď
Nový field errorCz na BaseResultEntity (setError path), nebo exception context
['errorCz' => …, 'source' => …] u throw-pattern controllerů — BC zachována.
AI backend (Gemini)
- Klient
App\Services\Ai\GeminiClient(implementujeAiTextClient) — veřejné Generative Language API (generativelanguage.googleapis.com) + API klíč, ne Vertex AI / ADC (SovaNG běží on-prem, ne na GCP). - Config v
local.neon:parameters.ai.geminiApiKey(prázdný = AI vypnutá, běží jen static + cache + raw), model vai.geminiModel. - Rate limit 6 AI volání / hodinu (server-wide, přes
COUNTnadcarrier_error_translation WHERE source='ai'). AnthropicClient(Claude) zůstává v kódu jakoautowired: falsepro případný návrat.
Model se nastavuje aliasem gemini-flash-lite-latest, ne pinned verzí — Google blokuje
gemini-2.5-flash-lite pro nové projekty (404 „no longer available to new users"). Volání má
thinkingBudget: 0 (textová transformace, ne uvažování) a hard timeout 8 s, aby AI nezpomalila
odpověď skladovému systému. Po změně configu je nutné smazat temp/cache (zkompilovaný DIC).
Push-styled (Alza volá naše REST endpointy). Dva partneři rozlišeni přes customer_id:
1017086 (VAPOL, Karat path) a 74 (BIORUZE, L4U path).
Endpointy (API V1, prefix /api/v1)
POST /drop/alza/order/{order}— Insert: lokální DB + Karat doklad + rezervace + poznámka „Waitting for Confirm".POST /drop/alza/order/{order}/confirm— Confirm: dispatch v Karatu + přepis poznámky na „Potvrzeno".DELETE /drop/alza/order/{cancelOrder}— Storno objednávky.POST /drop/alza/order/{order}/extend— Prodloužení platnosti rezervace.GET /drop/alza/order/{order}/delivery-address?customerId=X— Doručovací adresa objednávky (data 1:1 se starou sovou):deliveryAddressklíčovaný orderId (10 polí adresy + 6 z objednávky) +errorCode/errorMessage. Nahrazuje sova/api/vapol/alza/{doklad}/orderDeliveryAddress; data skládají modely (AlzaOrderAddress::toApiArray+AlzaOrder::getDeliveryApiExtraFields).
Zpětná kompatibilita starých sova URL
Po přepojení DNS sova.vapol.cz → apivapol volá Alza dál staré URL, na které je
nakonfigurovaná: /api/alza/order/… (stará sova, Nette Restful). Tvar cesty za order je
shodný s novým Apitte API, liší se jen prefix. BcUrlRewriteDispatcher přepíše cestu
před routingem:
/api/alza/order/{…}→/api/v1/drop/alza/order/{…}(insert / confirm / cancel / extend)
Rozsah je jen Alza order endpointy (Alza push). Staré /api/vapol/*
(shipment / delivery / tracking) jsou interní WMS, ne Alza — mimo BC. Nelze řešit přes Apache rewrite
(Apitte matchuje cestu z REQUEST_URI, interní rewrite ji nezmění) ani request decoratorem
(běží až po routingu) — proto custom dispatcher. Query string (?token=) zůstává zachovaný.
Pozor (bezpečnost): AlzaController ?token= čte, ale
nevaliduje, a RequestAuthenticationDecorator (IP allowlist Alzy) je v
services.neon zakomentovaný → order endpointy jsou aktuálně bez ověření. Před ostrým
přepojením DNS zvážit aktivaci auth decoratoru.
Klíčové soubory
- app/Api/Module/V1/Drop/AlzaController.php
- app/Api/Dispatcher/BcUrlRewriteDispatcher.php (BC staré sova URL → Apitte, registrace
api.core.dispatcherv services.neon) - app/Model/Service/Drop/AlzaManager.php
- app/Services/RemoteApi/AlzaApiService.php
- app/Model/Context/LocalTables/AlzaOrder.php (konstanty
ALZA_DROP_*,LOCAL_STATE_*,DELIVERY_ACTION_*) - app/Presenters/AlzaDropPresenter.php (admin grid + detail)
Local state číselník (api_alza_orders.local_state)
Jednotný číselník v AlzaOrder::LOCAL_STATE_META — pouze tyto hodnoty se zapisují.
Static getLocalStates() vrací mapping klíč → CZ label pro grid filter + badge renderer.
| Konstanta | Hodnota | Popis |
|---|---|---|
LOCAL_STATE_CREATED | created | Po Insert — Karat doklad vytvořen |
LOCAL_STATE_CONFIRMED | confirmed | Po Confirm — Karat dispatch OK |
LOCAL_STATE_SHIPMENT_CREATED | sc | createShipment OK |
LOCAL_STATE_SHIPMENT_DEPARTURE | sd | shipmentDeparture OK — odesláno |
LOCAL_STATE_SHIPMENT_DELETED | shipmentDeleted | deleteShipment OK |
LOCAL_STATE_DELIVERY_REJECTED | deliveryRejected | Alza delivery Rejected |
LOCAL_STATE_DELIVERY_CANCELED | deliveryCanceled | Alza delivery Canceled |
LOCAL_STATE_STORNO | storno | cancelOrder z Alzy |
LOCAL_STATE_UNAVAIL_ITEMS | unavailable | Fatal: nedostupné položky |
LOCAL_STATE_SD_ERROR | sd_error | Fatal: shipmentDeparture selhal |
LOCAL_STATE_SHIP_CANCEL_ERROR | ship_cancel_error | Fatal: deleteShipment selhal |
LOCAL_STATE_ERROR | error | Fatal: generic (dispatch/import fail) |
DELIVERY_ACTION_REJECTED / _CANCELED (hodnoty Rejected / Canceled) NEJSOU local_state — jsou to inbound tokens z Alza deliveryResult API. AlzaOrder::setDeliveryResult() je mapuje na interní LOCAL_STATE_DELIVERY_REJECTED/_CANCELED.
Cron / diagnostika
/console/alza-avail/avail?type=update&partner=…— availability sync (VAPOL: přesKaratAvailabilitySourcezw_SOVA_availability_v2, BIORUZE: přes L4U)/console/alza-test-vapol/insert-and-confirm?nomen=…&skipStorno=1— E2E test proti ostré Karat DB (Insert + Confirm + volitelně Storno)
Ruční storno (admin detail)
Tlačítko „Stornovat" na AlzaDropPresenter detailu → handleStorno →
AlzaManager::adminStornoOrder. Routuje podle partnera: VAPOL = storno
v Karatu (procedura user_o_obj_storno_op, guard canCancelKaratOrder) + lokální
storno stav; BIORUZE jde přes L4U (ne Karat) → jen lokální storno,
L4U ručně. Do Alza API neposílá nic. Tlačítko je partner-aware (jiný text pro VAPOL vs BIORUZE).
Idempotence + email notifikace
Opakovaný order/insert pro stejnou existující objednávku vrátí errorCode 0 (success), ne 409. Sověžij chování 1:1.
Fatal state → email na monitor@vapol.cz přes DropErrorNotifier (viz Sdílená vrstva níže), error_notified_ts guarduje před opakovaným spamem.
Historický fix (2026-07-10): confirmAlzaOrder při chybě aktualizace lokální
objednávky/adresy dělal return $e (Throwable), ale AlzaController::confirmOrder
návratovou hodnotu nekontroluje → Alze se vracelo HTTP 200 success, přestože confirm
interně selhal a objednávka zůstala ve error stavu. Fix: vyhodit ClientErrorException,
kterou controller přemapuje na 400. Zároveň odstraněny leftover bdump()
z produkčních Alza/import cest (leak HMAC tokenu při zapnutém debug módu).
Pull-styled. Apivapol pollá Allegro REST API (OAuth2 token refresh). DPD CZ shipment pro objednávky z polské Allegro.
Klíčové soubory
- app/Model/Service/AllegroManager.php
- app/Services/RemoteApi/AllegroApiService.php
- app/ConsoleModule/Presenters/AllegroSyncOrders*Presenter.php
- app/Presenters/AllegroPresenter.php (admin)
Cron actions
console-allegro-sync-orders— import nových objednávekconsole-allegro-sync-offers— sync stavů offerconsole-allegro-sync-orders-shipping— shipment + invoiceconsole-allegro-messaging— komunikace s zákazníky
Typ_expedice allegro-drop-0, sove Allegro pattern zachován.
Kaufland Global Marketplace. Specifikum: 1 Kaufland order může obsahovat víc units (per-sku samostatné objednávky), které sloučíme do 1 Karat dokladu.
Klíčové soubory
- app/Model/Service/KauflandManager.php
- app/Services/RemoteApi/KauflandApiService.php
- app/Model/Context/LocalTables/KauflandOrderUnitOrder.php (konstanta
KOD_CENIKU) - app/ConsoleModule/Presenters/Kaufland*Presenter.php
Typ_expedice kaufland-drop-0, typ_uhrady PK, kod_dopravy D01.
Historický bug (2026-07-02): variable shadowing v KauflandOrdersPresenter::actionDownloadOrders — vnější
$ordersUnits (all nedokladované) přepisoval vnitřní $orderUnits (aktuální group), takže všechny units napříč
všemi Kaufland orders dostávaly stejný karat_doklad + www_doklad. Fix: použít $orderUnits uvnitř foreach cyklu.
Detekce obětí: SELECT www_doklad, COUNT(DISTINCT kaufland_order_id) FROM kaufland_order_unit GROUP BY www_doklad HAVING COUNT(DISTINCT kaufland_order_id) > 1.
Decathlon B2B partner. Pull objednávek + shipment notifications.
Klíčové soubory
- app/Model/Service/DecathlonManager.php
- app/Services/RemoteApi/DecathlonApiService.php
- app/ConsoleModule/Presenters/DecathlonSyncOrders*Presenter.php
- app/Presenters/DecathlonPresenter.php (admin)
Typ_expedice decathlon-drop-0.
Mall Slovenia. Pull pattern (apivapol je klient, polluje Mall API). MPAPI SDK NEPOUŽÍVÁM — vlastní tenký REST klient.
Klíčové konstanty
MallOrder::MALL_SI_PARTNER_ID = '01034818'(Karat fakturační partner)MALL_DROP_RADA_SI = 'ML',MALL_DROP_DENIK = '31'MALL_DROP_EXPEDITION_TYPE = 'mall-drop-0'MALL_WAITING_FOR_CONFIRM_NOTE = 'Waitting for Confirm'(překlep záměrně 1:1)MALL_WWW_DOKLAD_PREFIX = 'MLL'MALL_TRACKING_URL_BASE_BY_DELIVERY_METHOD(base URL pro tracking odkaz; zatím prázdné — doplnit reálné SI URL)
REST endpointy (pro sklad Lora / WMS)
GET /api/v1/drop/mall/order/{doklad}/status(MallController) — aktuální stav Mall objednávky živě z Mall API. Vstup = Karat doklad (nebo Mall order_id). Vrací{orderStatus: <celé tělo Mall odpovědi>, errorCode, errorMessage}(data 1:1 se sovou).errorCode -1= neplatná objednávka → HTTP 400;1= Mall neodpověděl (orderStatus=false) → HTTP 200. Nahrazuje sova/api/vapol/mall-order/{doklad}/orderStatus.GET /api/v1/drop/mall/order/{order}/delivery-address?customerId=X(MallController) — doručovací adresa objednávky. Vrací identickou strukturu jako Alza EP (deliveryAddress[ORDER] = 16 polí+errorCode+errorMessage), aby ji Lora četla 1:1 pro obě platformy. Data skládají modelyMallOrderAddress::toApiArray()(10 adresních polí, mapováno na Alza klíče: company→company_name, name→address_name, street→street_with_number, note='') +MallOrder::getDeliveryApiExtraFields()(6 order-level polí: shipping_carrier_identification z delivery_method, cod, currency, payment_vs=purchase_id, shipment_value=null).errorCode -1= objednávka bez Karat dokladu → HTTP 400;-2= adresa nenalezena → HTTP 400;0→ HTTP 200. POZOR: na rozdíl od Alzy secustomerIdneporovnává (Mall customer_id = ID kupujícího, ne partner) — sova to řešila stejně. Replikace sovaApiVapolModule\MallPresenter::actionReadOrderDeliveryAddress.POST /api/v1/drop/general/set-order-tracking-number— shipping-push (viz níže).
Push stavů do Mall
Do Mall se stav objednávky propisuje na těchto místech (jinak apivapol stavy jen čte):
| Kdy | Co se pošle | Odkud |
|---|---|---|
| Po importu (cron / ruční) | confirmed=true | MallManager::importOneOrderFromDetail (krok 5) |
| Storno (cron) | confirmed=true | cancelOneOrder |
| Expedice (shipped) | status=shipped + tracking_number (+ tracking_url) | MallManager::setOrderTrackingNumber |
| Doručení / vrácení (cron) | status=delivered|returned (+ delivered_at) | applyTrackingStatusUpdate (check-delivery) |
| Ruční admin | status + confirmed=true | adminConfirmOrderToMall / ruční nástroje |
Shipping-push (shipped + tracking) je vstupní bod volaný externím
expedičním systémem přes REST: POST /api/v1/drop/general/set-order-tracking-number
s {drop:'mall', karat_doklad, tracking_number, carrier} (sdílený
GenerallController). Teprve tímto se objednávka dostane do shipped,
což je předpoklad, aby ji začal sledovat check-delivery cron
(filtr status='shipped'). Port sova MallOrderPresenter::actionReadSetOrderTrackingNumber.
Ruční nástroje
/mall-drop/manual (odkaz „Mall — ruční nástroje" v menu) — admin formulář:
(1) ruční import jedné objednávky podle order_id s krokovým logem
(status nechat nevyplněný = potvrdit jen confirmed; stejné jako cron),
(2) stažení a pretty-print JSON detailu objednávky z Mall (read-only).
Ruční storno: tlačítko na MallDropPresenter detailu →
handleStorno → MallManager::adminStornoOrder — storno v Karatu (procedura
user_o_obj_storno_op, guard canCancelKaratOrder) + lokální cancelled.
Na Mall API neposílá nic (na rozdíl od cron cancelOneOrder, který pushuje
confirmed=true). Storno lze i z Karat detailu (KaratOrderPresenter, čistě op_zahlavi).
Transakční bezpečnost importu
importOneOrderFromDetail je idempotentní resumable automat řízený flagy
(karat_doklad / reserved / confirmed): Karat insert → confirm →
teprve pak MALL confirmed=true (pořadí brání „confirmed v Mall bez Karatu").
Anti-duplicita: ERP guard KaratOrderManager::getKaratDokladByWwwDoklad (unikátní
www_doklad = MLL+orderId, ne op_zahlavi.objednavka — ta je cross-platform kolizní).
Souběh cronů řeší PG advisory lock (MallManager::runOrderSyncLocked).
Cron actions
| Interval | Akce |
|---|---|
*/5 | api-get-unconfirmed-orders — import nových |
*/10 | api-get-cancelled-orders — sync zrušení |
*/15 | api-update-availability?type=update — dostupnost |
*/30 | sync-order-status-by-mall — Mall status sync |
0 * * * * | check-delivery — DPD/Ulozenka tracking |
0 2 * * * | api-update-availability?type=full — full produkt sync |
0 6 1 * * | generate-order-list-csv — měsíční billing |
Klíčové soubory
- app/Model/Service/MallManager.php (orchestrace)
- app/Services/RemoteApi/MallApiService.php (REST klient)
- app/Services/RemoteApi/UlozenkaApiService.php (SI tracking)
- app/Model/Context/LocalTables/MallOrder.php (konstanty)
- app/ConsoleModule/Presenters/ConsoleMallPresenter.php (10 actions)
- app/Presenters/MallDropPresenter.php (admin grid + detail + ruční nástroje + storno)
- app/Api/Module/V1/Controllers/Drop/MallController.php (order status endpoint pro Loru)
- app/Api/Module/V1/Controllers/Drop/GenerallController.php (shipping-push endpoint, větev mall)
BaseApiContext quirk
Mall response {result, paging, data} má BaseApiContext::setValues bug,
který přemapuje data na prázdné pole. Workaround: MallApiService::extractIds() /
extractData() / extractPaging() přes getOrigValues().
Sdílená vrstva drop platforem
Namespace App\Services\Drop\ — reuse infrastruktura pro Allegro / Alza / Mall / Decathlon / Kaufland
(viz feedback_drop_shared_interfaces memory). Cíl: nová drop platforma stačí implementovat interface,
nemusí duplikovat email pattern, fatal-state handling, grid renderer.
| Třída | Účel |
|---|---|
DropOrderInterface |
Kontrakt pro drop order entity. Implementují AllegroOrder, AlzaOrder, MallOrder, DecathlonOrder, KauflandOrderUnitOrder. Metody: getDropPlatformName(), getOrderExternalId(), getPartnerLabel(), hasFatalError(), getFatalStateLabel/Short(), getRecommendedAction(), getDetailUrl(), getErrorNotifiedTs(), markErrorNotified(), clearErrorNotified(). |
DropErrorNotifier |
Jednotný email pipeline. Odesílá na monitor@vapol.cz (from it@vapol.cz) když hasFatalError() a error_notified_ts je NULL. Po odeslání volá markErrorNotified() → idempotency guard proti spamu. Selhání mailer nesmí shodit business flow (try/catch + Tracy log). |
DropSummary + DropSummaryProviderInterface |
Value object + kontrakt pro uniform „Total/OK/Cancel/Error" summary za N dní. Managery vrací DropSummary z getUnifiedSummary($days=30). Používá se v grid pill row nad každou drop stránkou + na Drop Dashboardu. |
DropOrderSearchService |
Cross-platform search po karat_doklad / external ID / www_doklad / tracking_number (Alza pozor: cs_shipmentNumber, ne tracking_number). Vrací DropOrderReference[] — shallow objekty pro Dashboard search. |
DropOrderRepository |
UNION SQL nad 5 tabulkami: findTodayOrders($limit=30), findFatalInbox($days=14, $limit=50). Používá Dashboard. Cross-platform SQL patří sem, ne do drop-specific manageru (feedback_no_sql_in_presenter). |
Backward compat: Decathlon + Kaufland manageOrderError zachován v původním tvaru (odlišný email pattern it@vapol.cz ← monitor@vapol.cz + Kaufland má 2h cache rate limit) — nedotčeno kvůli produkční pipeline. Allegro + Alza managery volají DropErrorNotifier přes tenký wrapper manageOrderError().
Fatal state guard v DB
Sloupec error_notified_ts (timestamp) přidán na allegro_order, api_alza_orders, decathlon_order, kaufland_order_unit. Partial index pro efektivní inbox query:
CREATE INDEX api_alza_orders_fatal_unsent_idx
ON api_alza_orders (created_ts DESC)
WHERE local_state IN ('error','sd_error','ship_cancel_error','unavailable')
AND error_notified_ts IS NULL;
Nomen lookup — detail produktu
KaratProductPresenter — samostatná diagnostika „proč mi obj padla na tomto nomen".
3 casey: (A) je ve w_web3_nomenklatury — Doctrine detail, (B) není ve web3 ale je v Karatu — raw dba.nomenklatura
(SELECT *, 3-sloupcový layout), (C) neexistuje nikde — alert-danger.
Endpointy
GET /karat-product/— search form (Nette Form component, redirect na detail)GET /karat-product/detail/{id}— full-page detail (banner + body)GET /karat-product/drawer/{id}— AJAX fragment (bez layoutu,setLayout(false)) pro Bootstrap Offcanvas
Klíčové soubory
- app/Presenters/KaratProductPresenter.php
- app/Presenters/templates/KaratProduct/_detail_body.latte (sdílený body — 3 case)
- app/Presenters/templates/KaratProduct/detail.latte (full-page)
- app/Presenters/templates/KaratProduct/drawer.latte (fragment)
- app/Model/Karat/KaratService.php:
getNomenklaturaRow($code)+getKartyRows($code) - app/Model/Service/KaratProductManager.php:
getNomenFromKaratRaw($code)+getKartyRows($code)
Sklad JOIN
- Case A (Web3):
$web3->getSklad()(Doctrine LAZY) —dispKusu,datumDostupnosti,typSkladu,userPotvrzeneDod - Case B (Karat):
SELECT * FROM dba.karty WHERE KARTA = ?per SKLAD ID —stav_rtreal-time zůstatek, rezerva, objednáno
Global nomen drawer (Bootstrap 5 Offcanvas)
@layout.latte obsahuje globální #nomenDrawer Offcanvas + JS handler.
Klik na libovolný odkaz s .js-nomen-drawer class → fetch('/karat-product/drawer/{code}') → inject do drawer body.
Ctrl+/Cmd+/Shift+/middle-click → standardní <a href> navigace na full-page (fallback pro sdílení URL).
Tracy Debug Bar je odstřižen z AJAX response na klientu.
Použití v templates: {include _nomen_link.latte, code => $item->getCode(), enabled => $localOrder->isVapol()}
(shared include, backward compat přes $enabled=false → plain <code> bez linku).
Aktivní v: AlzaDrop/detail.latte (jen VAPOL obj), SyncDropLogPresenter grid.
Deprecated metody
Web3Nomenklatura::getRezervovavoCount() a getActualCount() volaly neexistující
getCartItems() (legacy relace w_web3_cart_items odstraněna). Označeno @deprecated,
vrací bezpečné hodnoty (0 / dispKusu). Rezervace se v novém apivapol nedrží ve web3 —
pokud potřebuješ real-time rezervace, čti z Karat op_polozky.
Drop Dashboard
/drop-dashboard/ — hlavní přehledová obrazovka pro drop sekci. Snapshot přes všech 5 platforem
bez nutnosti procházet 5 gridů samostatně.
Sekce
- Agregate stats — 5 karet s brand barvami platforem (Allegro
#FF5A00, Alza#00A884, Mall#E5006D, Decathlon#0082C3, Kaufland#E10915). Stat pilly „Celkem 30 dní / OK / Cancel / Chyby" per platforma přesgetUnifiedSummary(30). - Dnešní objednávky — UNION přes 5 tabulek (
DropOrderRepository::findTodayOrders(30)), řazeno DESC. - Fatal error inbox — obj s
hasFatalError()max 14 dní zpět (findFatalInbox(14, 50)). Deep-link na detail obj. - Sync status — poslední úspěšný sync per
drop_namezsync_drop_log(SyncDropLogger::getLastRunPerDrop()).
Search bar
Nette Form component (createComponentSearchForm) → onSuccess redirect na ?q=….
Cross-platform lookup přes DropOrderSearchService::search($q) po karat_doklad, external ID,
www_doklad, tracking_number. Alza tracking je v cs_shipmentNumber, ne tracking_number.
Sjednocené UI napříč gridy
Sdílený Latte include templates/_drop_pill_row.latte — 4 pill boxy (Total/OK/Cancel/Chyby) nad každým drop gridem.
Renderuje se z $unifiedSummary = $manager->getUnifiedSummary(30). Platform-specific rozpad (Allegro error kategorie,
Alza per-partner) je pod tím v každém default.latte samostatně.