Preise pro Storefront/Preisliste pushen #18

Closed
opened 2026-05-10 16:44:53 +00:00 by csaeum · 1 comment
csaeum commented 2026-05-10 16:44:53 +00:00 (Migrated from gitlab.localdomain)

Artikelpreise storefront-spezifisch nach Shopware pushen:

  • Preis aus der im Storefront konfigurierten ERPNext Preisliste auslesen
  • Endpoint: Preis-Objekt im Product-Body (price Array mit currencyId)
  • EUR und CHF separat behandeln — niemals mischen
  • Shopware Currency ID aus Storefront-Konfiguration
  • Nur Artikel pushen für die ein Preis in der Preisliste hinterlegt ist
Artikelpreise storefront-spezifisch nach Shopware pushen: - Preis aus der im Storefront konfigurierten ERPNext Preisliste auslesen - Endpoint: Preis-Objekt im Product-Body (`price` Array mit `currencyId`) - EUR und CHF separat behandeln — niemals mischen - Shopware Currency ID aus Storefront-Konfiguration - Nur Artikel pushen für die ein Preis in der Preisliste hinterlegt ist
Owner

Implementiert (shopware6/api/price.py, push_prices()).

Zwei Entscheidungen, die nicht 1:1 aus dem Issue-Text ableitbar waren, vorab mit Christian geklärt:

  1. ERPNext-Preisliste ist Brutto (B2C, z.B. 39,90 €) — gross wird 1:1 aus price_list_rate übernommen, net wird berechnet.
  2. Steuer-Mapping wurde mit in #18 aufgenommen (statt separates Issue): die echte Shopware-taxId wird jetzt korrekt gesetzt, nicht mehr #16s beliebiger Platzhalter.

Live-getestete Erkenntnisse, die die ursprüngliche Annahme widerlegt haben:

  • price.linked: true bewirkt bei der Admin API keine serverseitige Berechnung — gross und net sind bei jedem Write immer beide Pflichtfelder (Test: net weggelassen → 400 "This field is missing."). linked ist rein ein UI-Hinweis für die Shopware-Administration.
  • Im Admin-UI live beobachtet: Shopware selbst rundet den berechneten Netto-Wert nicht auf 2 Nachkommastellen (49,99 € brutto / 19% → 42.008403361345). Eine einfache, ungerundete Python-Float-Division (gross / (1 + tax_rate/100)) reproduziert das nahezu exakt (42.00840336134454) — genau das war Christians Rundungssorge, und eine 2-Dezimalstellen-Rundung hätte sie tatsächlich bestätigt.

Steuersatz-Ermittlung (neu, kein Vorbild in Julian/Marcel): Item.taxes → Item Tax Template → Item Tax Template Detail.tax_rate gibt den Satz (z.B. 19.0), gematcht gegen Shopwares POST /api/search/tax-Entitäten per taxRate. Kein Item Tax Template zugeordnet → skipped_no_tax_rate statt geraten.

Bekannte, dokumentierte Einschränkung: zwei Storefronts mit gleicher Currency aber unterschiedlichem Preis für dasselbe Item lassen sich mit einem flachen price-Array nicht abbilden (Shopwares Lösung wären Advanced-Pricing-ruleId-Einträge, bewusst nicht übernommen — zu viel Komplexität für den Issue-Scope). Wird live-verifiziert als failed erkannt statt stillschweigend ein Preis zu bevorzugen.

Weitere Punkte:

  • Ein PATCH pro Item, price-Array mit einem Eintrag je distinct Currency über alle aktiven Storefronts des Items (mehrfach-Currency-Array-Unterstützung laut offizieller Shopware-Doku bestätigt, in der Test-Instanz mangels CHF-Konfiguration aber nicht live durchgetestet).
  • Items ohne Preis in irgendeiner Storefront-Preisliste: skipped_no_price.
  • Push nur für einfache Items mit bereits gesetzter shopware_product_id (#16); Templates/Varianten bleiben #19.
  • Neuer Button "Push Prices" auf Shopware Account.

Volle Begründung: docs/architecture.md#issue-18.

Live-Round-Trip inkl. Preis-Konflikt-Fall erfolgreich getestet (Testdaten danach entfernt). Deploy auf den 4 App-Containern durchgeführt.

Implementiert (`shopware6/api/price.py`, `push_prices()`). **Zwei Entscheidungen, die nicht 1:1 aus dem Issue-Text ableitbar waren, vorab mit Christian geklärt:** 1. **ERPNext-Preisliste ist Brutto** (B2C, z.B. 39,90 €) — `gross` wird 1:1 aus `price_list_rate` übernommen, `net` wird berechnet. 2. **Steuer-Mapping wurde mit in #18 aufgenommen** (statt separates Issue): die echte Shopware-`taxId` wird jetzt korrekt gesetzt, nicht mehr #16s beliebiger Platzhalter. **Live-getestete Erkenntnisse, die die ursprüngliche Annahme widerlegt haben:** - `price.linked: true` bewirkt bei der Admin API **keine** serverseitige Berechnung — `gross` und `net` sind bei jedem Write immer beide Pflichtfelder (Test: `net` weggelassen → `400 "This field is missing."`). `linked` ist rein ein UI-Hinweis für die Shopware-Administration. - Im Admin-UI live beobachtet: Shopware selbst rundet den berechneten Netto-Wert **nicht** auf 2 Nachkommastellen (49,99 € brutto / 19% → `42.008403361345`). Eine einfache, ungerundete Python-Float-Division (`gross / (1 + tax_rate/100)`) reproduziert das nahezu exakt (`42.00840336134454`) — genau das war Christians Rundungssorge, und eine 2-Dezimalstellen-Rundung hätte sie tatsächlich bestätigt. **Steuersatz-Ermittlung** (neu, kein Vorbild in Julian/Marcel): `Item.taxes` → `Item Tax Template` → `Item Tax Template Detail.tax_rate` gibt den Satz (z.B. `19.0`), gematcht gegen Shopwares `POST /api/search/tax`-Entitäten per `taxRate`. Kein Item Tax Template zugeordnet → `skipped_no_tax_rate` statt geraten. **Bekannte, dokumentierte Einschränkung**: zwei Storefronts mit gleicher Currency aber unterschiedlichem Preis für dasselbe Item lassen sich mit einem flachen `price`-Array nicht abbilden (Shopwares Lösung wären Advanced-Pricing-`ruleId`-Einträge, bewusst nicht übernommen — zu viel Komplexität für den Issue-Scope). Wird live-verifiziert als `failed` erkannt statt stillschweigend ein Preis zu bevorzugen. **Weitere Punkte**: - Ein PATCH pro Item, `price`-Array mit einem Eintrag je distinct Currency über alle aktiven Storefronts des Items (mehrfach-Currency-Array-Unterstützung laut offizieller Shopware-Doku bestätigt, in der Test-Instanz mangels CHF-Konfiguration aber nicht live durchgetestet). - Items ohne Preis in irgendeiner Storefront-Preisliste: `skipped_no_price`. - Push nur für einfache Items mit bereits gesetzter `shopware_product_id` (#16); Templates/Varianten bleiben #19. - Neuer Button "Push Prices" auf `Shopware Account`. Volle Begründung: [docs/architecture.md#issue-18](../../src/branch/shopware6-dach/docs/architecture.md#issue-18-push-item-prices-and-tax-per-storefront). Live-Round-Trip inkl. Preis-Konflikt-Fall erfolgreich getestet (Testdaten danach entfernt). Deploy auf den 4 App-Containern durchgeführt.
Sign in to join this conversation.
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
Frappe-Projekte/ecommerce_integrations#18
No description provided.