Erweitere Schema fuer Shopify Delta Import
This commit is contained in:
@@ -0,0 +1,68 @@
|
|||||||
|
BEGIN;
|
||||||
|
|
||||||
|
-- Additive Shopify delta-sync identities. Existing Wix and direct orders,
|
||||||
|
-- their lines and their lot allocations remain unchanged.
|
||||||
|
|
||||||
|
ALTER TABLE sales_order
|
||||||
|
ADD COLUMN IF NOT EXISTS shopify_order_gid TEXT,
|
||||||
|
ADD COLUMN IF NOT EXISTS shopify_order_name TEXT,
|
||||||
|
ADD COLUMN IF NOT EXISTS shopify_created_at TIMESTAMP,
|
||||||
|
ADD COLUMN IF NOT EXISTS shopify_updated_at TIMESTAMP,
|
||||||
|
ADD COLUMN IF NOT EXISTS shopify_financial_status TEXT,
|
||||||
|
ADD COLUMN IF NOT EXISTS shopify_fulfillment_status TEXT;
|
||||||
|
|
||||||
|
ALTER TABLE sales_order_line
|
||||||
|
ADD COLUMN IF NOT EXISTS shopify_line_item_gid TEXT,
|
||||||
|
ADD COLUMN IF NOT EXISTS shopify_variant_gid TEXT,
|
||||||
|
ADD COLUMN IF NOT EXISTS shopify_product_gid TEXT,
|
||||||
|
ADD COLUMN IF NOT EXISTS sku TEXT;
|
||||||
|
|
||||||
|
ALTER TABLE external_item_alias
|
||||||
|
ADD COLUMN IF NOT EXISTS shopify_product_gid TEXT,
|
||||||
|
ADD COLUMN IF NOT EXISTS shopify_variant_gid TEXT;
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS party_external_identity (
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
party_id BIGINT NOT NULL REFERENCES party(id) ON DELETE CASCADE,
|
||||||
|
source_system TEXT NOT NULL,
|
||||||
|
external_id TEXT NOT NULL,
|
||||||
|
observed_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||||
|
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
|
||||||
|
CONSTRAINT uq_party_external_identity_source_external UNIQUE (source_system, external_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
ALTER TABLE sales_order
|
||||||
|
DROP CONSTRAINT IF EXISTS chk_sales_order_source;
|
||||||
|
|
||||||
|
ALTER TABLE sales_order
|
||||||
|
ADD CONSTRAINT chk_sales_order_source
|
||||||
|
CHECK (order_source IN ('wix', 'direct', 'shopify'));
|
||||||
|
|
||||||
|
ALTER TABLE sales_order
|
||||||
|
DROP CONSTRAINT IF EXISTS chk_sales_order_payment_status;
|
||||||
|
|
||||||
|
ALTER TABLE sales_order
|
||||||
|
ADD CONSTRAINT chk_sales_order_payment_status
|
||||||
|
CHECK (payment_status IN ('pending', 'authorized', 'paid', 'partially_refunded', 'refunded', 'voided', 'unknown'));
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS uq_sales_order_shopify_order_gid
|
||||||
|
ON sales_order(shopify_order_gid)
|
||||||
|
WHERE shopify_order_gid IS NOT NULL;
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS uq_sales_order_line_shopify_line_item_gid
|
||||||
|
ON sales_order_line(shopify_line_item_gid)
|
||||||
|
WHERE shopify_line_item_gid IS NOT NULL;
|
||||||
|
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS uq_external_item_alias_shopify_variant_gid
|
||||||
|
ON external_item_alias(shopify_variant_gid)
|
||||||
|
WHERE shopify_variant_gid IS NOT NULL;
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_party_external_identity_party
|
||||||
|
ON party_external_identity(party_id);
|
||||||
|
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_sales_order_shopify_updated_at
|
||||||
|
ON sales_order(shopify_updated_at DESC)
|
||||||
|
WHERE shopify_order_gid IS NOT NULL;
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
@@ -13,6 +13,7 @@ Diese Referenz ordnet die aktuellen Tabellen, Views und technischen DB-Artefakte
|
|||||||
- `party`
|
- `party`
|
||||||
- `address`
|
- `address`
|
||||||
- `contact`
|
- `contact`
|
||||||
|
- `party_external_identity`
|
||||||
|
|
||||||
### `bestellungen`
|
### `bestellungen`
|
||||||
|
|
||||||
|
|||||||
+113
@@ -0,0 +1,113 @@
|
|||||||
|
# erp.import-integration.shopify_delta_order_import
|
||||||
|
Stand: 2026-08-12
|
||||||
|
Status: Verbindliche Prozess-Spezifikation
|
||||||
|
|
||||||
|
## 1. Zweck
|
||||||
|
|
||||||
|
Read-only-Abgleich von Shopify-Bestellungen nach dem ERP-Stichtag und identifier-only Übergabe qualifizierter Bestellungen an `erp/bestellungen`.
|
||||||
|
|
||||||
|
## 2. Prozess-Einbettung
|
||||||
|
|
||||||
|
Manuell startbarer Initial-Deltalauf und später wiederverwendbarer Reconciliation-Prozess im Submodul `erp/import-integration`. Er ist vom Webhook-Empfang getrennt.
|
||||||
|
|
||||||
|
## 3. Input
|
||||||
|
|
||||||
|
- `cutoff_timestamp`
|
||||||
|
- optional `dry_run`
|
||||||
|
|
||||||
|
Es werden keine vorbereiteten Shopify-Geschäftsdaten an nachgelagerte Module übergeben.
|
||||||
|
|
||||||
|
## 4. Exakter Prozessablauf
|
||||||
|
|
||||||
|
1. `cutoff_timestamp` und `dry_run` validieren.
|
||||||
|
2. Read-only Shopify-Bestellungen mit `createdAt` nach dem Stichtag in stabiler Reihenfolge laden.
|
||||||
|
3. Stornierte oder vollständig erstattete Bestellungen als nicht lagerwirksam klassifizieren und nur technisch protokollieren.
|
||||||
|
4. Für jede qualifizierte Bestellung die Shopify Order-GID idempotent gegen `sales_order.shopify_order_gid` prüfen.
|
||||||
|
5. Nur die Shopify Order-GID an die Bestell-Schnittstelle übergeben; diese lädt und projiziert die erforderlichen Shopify-Daten selbst.
|
||||||
|
6. Bei `dry_run` keine fachlichen DB-Writes, Lagerbewegungen oder externen Aufrufe ausführen.
|
||||||
|
7. Keine Shopify-Mutation, keine n8n-Zustellung, kein Klaviyo-Ereignis, keine Kundenmail und keine Label-Aktion ausführen.
|
||||||
|
8. Den technischen Lauf in `process_runs` abschliessen.
|
||||||
|
|
||||||
|
Read sources:
|
||||||
|
|
||||||
|
- Shopify Admin API, ausschliesslich read-only
|
||||||
|
- `sales_order` für die Idempotenzprüfung
|
||||||
|
- `shopify_webhook_event` und `process_runs` als technische Eingangs-/Laufdaten
|
||||||
|
|
||||||
|
Write targets:
|
||||||
|
|
||||||
|
- `process_runs`
|
||||||
|
- technische Ergebnisdaten im owning Submodul
|
||||||
|
- Bestelldaten ausschliesslich über die Schnittstelle von `erp/bestellungen`
|
||||||
|
|
||||||
|
## 5. Batch, Betriebsmodell und Einbettung
|
||||||
|
|
||||||
|
Der Initiallauf verarbeitet den festen Zeitraum nach dem bestehenden ERP-Stichtag seriell. Spätere Reconciliation-Läufe nutzen denselben Prozess mit einem definierten Wasserzeichen. Keine Parallelisierung.
|
||||||
|
|
||||||
|
## 6. Output
|
||||||
|
|
||||||
|
Kompaktes Ergebnis mit geprüfter, übersprungener, bereits vorhandener und übergebener Bestellanzahl.
|
||||||
|
|
||||||
|
## 7. Erfolgskriterien
|
||||||
|
|
||||||
|
- nur Bestellungen nach dem Stichtag werden berücksichtigt
|
||||||
|
- stornierte/erstattete Bestellungen sind nicht lagerwirksam
|
||||||
|
- jede Shopify Order-GID wird höchstens einmal als ERP-Bestellung angelegt
|
||||||
|
- der Dry-Run verändert keine fachlichen Daten
|
||||||
|
- n8n, Klaviyo, Mail, Labels und Shopify bleiben unbeeinflusst
|
||||||
|
|
||||||
|
## 8. Fehlerschranke
|
||||||
|
|
||||||
|
Ein Shopify-API- oder technischer DB-Fehler beendet den Lauf hart. Eine fachlich nicht abbildbare Einzelbestellung wird als Klärfall gezählt; weitere Bestellungen werden verarbeitet.
|
||||||
|
|
||||||
|
## 9. Fachliche Betriebsregel
|
||||||
|
|
||||||
|
Die bestehenden 93 ERP-Bestellungen inklusive ihrer Chargen- und Lagerrelationen bleiben erhalten. Nur neuere, qualifizierte Shopify-Bestellungen erzeugen neue Bestellpositionen und Lagerbewegungen.
|
||||||
|
|
||||||
|
## 10. Sub-Prozess-Referenzen
|
||||||
|
|
||||||
|
- `erp.bestellungen.shopify_order_projection`
|
||||||
|
|
||||||
|
## 11. End-to-End Sub-Prozess-Kette
|
||||||
|
|
||||||
|
Delta-Scope bestimmen → Shopify read-only laden → Qualifikation → identifier-only Bestellübergabe → technischer Abschluss.
|
||||||
|
|
||||||
|
## 12. Sub-Prozess-Wiederverwendung
|
||||||
|
|
||||||
|
Der bestehende Shopify-API-Client und die vorhandene technische Laufpersistenz werden wiederverwendet. Die Bestell- und Lagerfachlichkeit bleibt in ihren owning Modulen.
|
||||||
|
|
||||||
|
## 13. Step-Liste
|
||||||
|
|
||||||
|
1. `validate_delta_scope`
|
||||||
|
2. `load_shopify_delta`
|
||||||
|
3. `classify_order_for_inventory`
|
||||||
|
4. `shopify_order_projection`
|
||||||
|
5. `finalize_delta_run`
|
||||||
|
|
||||||
|
## 14. Parallelisierung
|
||||||
|
|
||||||
|
Nicht anwendbar. Der aktuelle Delta-Scope ist klein und wird seriell, nachvollziehbar verarbeitet.
|
||||||
|
|
||||||
|
## 15. Output-Payload
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"status": "done|partial_success|failed",
|
||||||
|
"cutoff_timestamp": "ISO-8601 timestamp",
|
||||||
|
"dry_run": true,
|
||||||
|
"checked_orders": 0,
|
||||||
|
"skipped_cancelled_or_refunded": 0,
|
||||||
|
"already_imported": 0,
|
||||||
|
"handed_off": 0,
|
||||||
|
"clarification_order_gids": [],
|
||||||
|
"technical_run_id": 0
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 16. Done-Kriterien
|
||||||
|
|
||||||
|
- Stichtag und Qualifikationsregel sind umgesetzt und testbar.
|
||||||
|
- Shopify-Identitäten sind im Datenmodell eindeutig speicherbar.
|
||||||
|
- Bestehende Bestellungen und Chargenrelationen bleiben unverändert.
|
||||||
|
- Der Dry-Run ist nebenwirkungsfrei.
|
||||||
|
- Externe Kommunikation bleibt in diesem Prozess ausgeschlossen.
|
||||||
Reference in New Issue
Block a user