1.8.12
βοΈ Patch 1.8.12 β Rituals invoice PDF download & Otto offers-frame scraping¶
π Summary¶
- Rituals invoices (EUW / DACH) β reliable PDF download from Gmail: correct
click.c.rituals.comlink (invoicearia-label), HTML parsing, DACH two-step QR flow, and a public test endpoint. - Otto site prices β scrape via
/dcs/offers-page-frame/instead of blocked moin PDPs; resolvevariationIdfrom moin HEAD redirect; sync stores offers-frame URLs. - n8n invoice storage β shared
invoicesvolume on n8n + runners (/home/node/.n8n-files/invoices), same data asservice-invoiceand file-manager.
β¨ Improvements¶
Invoice β Rituals special case¶
| Before | After |
|---|---|
Any click.c.rituals.com near βZUR RECHNUNGβ |
Only anchors with aria-label β¦ Rechnung im PDF-Format β¦ |
Plain-text email body (no aria-label) |
HTML body for link extraction |
EUW search used full EUW234β¦ or wrong link β promotions page |
Strip EUW for Gmail search; PDF button link in shipping/invoice mail |
| DACH single-email assumption | Shipping mail β extract OR237018980 from QR β re-search 237018980 β invoice mail |
| Corrupt βPDFβ (HTML promotions saved as file) | Reject non-invoice redirects; verify %PDF magic bytes |
| No local test hook | POST /api/v1/invoice/gmail/test/rituals/{invoice_number} (public, step log) |
Verified: EUW234505767, DACH06758065 β valid PDFs downloaded in Docker.
Multi-repricer β Otto scraping¶
| Before | After |
|---|---|
Scrape https://www.otto.de/p/?moin=β¦ β HTTP 429 from server IP |
HEAD moin β canonical URL + variationId; offers-frame GET β 200 |
product_url built from moin or empty productDescription.productUrl |
Sync resolves /dcs/offers-page-frame/{item}?variationId=β¦ |
| marketplace-status shop link only | GET /api/v1/multi/otto/products/{sku}/shop-context for debugging |
| Offers-frame 404 / empty / blocked β failed scrape | Solo buybox β price toward max |
| Full PDP scrape as fallback | Offers page only β no moin PDP HTML load |
| Seller / buybox unknown after offers scrape β blind undercut | Parse buybox seller from .of_offers-row β span.of_offers-seller__retailer-name; is_in_buybox when seller is eCommerce GmbH |
Offers-page logic
- Resolve
offers_frame_urlvia marketplace-status + moin HEAD redirect. - Scrape
/dcs/offers-page-frame/{item}?variationId=β¦only. - Each
.js_of_offers-row.of_offers-rowβ price + seller; first row = buybox. - No offers page (404 / no rows / unreachable) β assume solo buybox β max price.
- Competing offers but buybox seller unknown β skip price change (no blind undercut).
Note: productDescription.productUrl in Otto Partner API is the sellerβs own URL (usually empty), not otto.de.
π§ Deploy¶
- Rebuild / restart
service-invoiceandservice-multi-repricer. - Rebuild docs if you publish patchnotes from the repo.
- No database migration.
- Rituals: re-run Otto/Rituals sync or wait for next Gmail download batch to pick up new logic.
- Otto: optional re-sync articles to refresh stored
product_urlto offers-frame URLs.
β Verify¶
-
Rituals EUW:
POST /api/v1/invoice/gmail/test/rituals/EUW234505767βsuccess: true,extracted_linkcontains invoice tracking URL,download_linkfile opens as PDF. -
Rituals DACH:
POST /api/v1/invoice/gmail/test/rituals/DACH06758065β steps show QR237018980and second email; PDF valid. -
Otto shop context:
GET /api/v1/multi/otto/products/{sku}/shop-context(auth) βoffers_frame_urlpopulated. -
Otto scrape logs:
offers-frame HTTP OKwithbuybox_seller=β¦,in_buybox=True/False(not moin PDP 429).
β οΈ Notes¶
- Rituals test endpoint is public (
PUBLIC_ENDPOINT_PREFIXESinservice-invoicemain.py) β use only on trusted networks or remove prefix after testing. - Otto full PDP may still 429 from datacenter IPs; offers-frame is the supported server-side path.
- Playwright + proxy still used for Rituals
click.c.rituals.comredirects when direct download fails.
Files touched¶
service-invoice
app/services/gmail.pyβ Rituals EUW/DACH flow, HTML extraction, aria-label link, PDF validation,test_rituals_invoice_flowapp/api/v1/endpoints/gmail.pyβPOST /gmail/test/rituals/{invoice_number}app/main.pyβ public prefix for Rituals test route
service-multi-repricer
app/services/otto/otto_service.pyβ offers-frame-only scrape, seller/buybox parsing, solo buybox fallbackapp/api/v1/endpoints/fbm_articles.pyβ FBM error flush on sync/recalc/export
infrastructure
docker-compose.yml,docker-compose-portainer.ymlβ sharedinvoicesvolume mounted on n8n + runners for invoice downloads
docs
docs/docs/patchnotes/1.8/1.8.12.mdβ this file