0d8353fb9c
Features: - Migration 0007: shipping_date column with automatic next-business-day calculation - New function trigger_excel_webhook() in order-import.php - SQL query for extracting Excel data from ERP database - Integration after successful order import - Documentation for n8n Postgres node configuration Changes: 1. db/migrations/0007_phase1_excel_webhook.sql - adds shipping_date column, trigger, next-business-day function 2. order-import.php - adds trigger_excel_webhook() function and integration point 3. docs/EXAKTE_POSTGRES_QUERY.sql - exact SQL query for n8n Postgres node 4. docs/N8N_POSTGRES_QUERY.md - comprehensive documentation 5. docs/N8N_POSTGRES_NODE.* - n8n node configurations 6. docs/N8N_EXCEL_WORKFLOW.json - complete workflow JSON 7. docs/N8N_NODE_COPY_PASTE.md - copy-paste ready instructions The implementation triggers an Excel webhook after every successful order import, sending all necessary data for Excel bookkeeping to n8n.
208 lines
6.1 KiB
Markdown
208 lines
6.1 KiB
Markdown
# Postgres Query für n8n Excel Node
|
|
|
|
## Übersicht
|
|
Diese Query extrahiert alle benötigten Daten für die Excel-Buchhaltung basierend auf einer Bestellnummer.
|
|
|
|
## Postgres Node Konfiguration für n8n
|
|
|
|
### Connection Details
|
|
```
|
|
Host: 192.168.1.199
|
|
Port: 55432
|
|
Database: naurua_erp
|
|
User: codex_db_user
|
|
Password: Ze90re0KAry8gyJ6eAx0Gf4IelEGI
|
|
SSL: Disabled (lokales Netzwerk)
|
|
```
|
|
|
|
### SQL Query für Excel-Daten
|
|
|
|
```sql
|
|
SELECT
|
|
-- Bestellinformationen
|
|
so.external_ref AS "Bestellnummer",
|
|
TO_CHAR(so.order_date, 'YYYY-MM-DD"T"HH24:MI:SS') AS "Bestelldatum",
|
|
TO_CHAR(so.shipping_date, 'YYYY-MM-DD') AS "Versanddatum",
|
|
|
|
-- Kundenadresse (Lieferadresse)
|
|
COALESCE(ad.first_name, '') AS "Vorname",
|
|
COALESCE(ad.last_name, '') AS "Nachname",
|
|
COALESCE(ad.street, '') AS "Strasse",
|
|
COALESCE(ad.house_number, '') AS "Hausnummer",
|
|
COALESCE(ad.zip, '') AS "PLZ",
|
|
COALESCE(ad.city, '') AS "Stadt",
|
|
COALESCE(ad.country_name, '') AS "Land",
|
|
|
|
-- Zahlungs- und Betragsinformationen
|
|
COALESCE(pm.code, '') AS "Zahlungsart",
|
|
COALESCE(so.amount_net, 0) AS "Gesamtbetrag_netto",
|
|
COALESCE(so.amount_shipping, 0) AS "Versandkosten",
|
|
COALESCE(so.total_amount, 0) AS "Gesamtbetrag_brutto",
|
|
COALESCE(so.amount_discount, 0) AS "Rabatt",
|
|
|
|
-- Produktzählungen (nur aktive Produkte)
|
|
COALESCE(SUM(CASE WHEN p.id = 8 THEN a.qty ELSE 0 END), 0) AS "#_ChagaFlaschen", -- CHAGA (ID 8)
|
|
COALESCE(SUM(CASE WHEN p.id = 5 THEN a.qty ELSE 0 END), 0) AS "#_ReishiFlaschen", -- 003.01 (ID 5)
|
|
COALESCE(SUM(CASE WHEN p.id = 9 THEN a.qty ELSE 0 END), 0) AS "#_ShiitakeFlaschen", -- SHIITAKE (ID 9)
|
|
COALESCE(SUM(CASE WHEN p.id = 6 THEN a.qty ELSE 0 END), 0) AS "#_LionsManeFlaschen" -- 005.02 (ID 6)
|
|
|
|
FROM sales_order so
|
|
-- Lieferadresse
|
|
LEFT JOIN address ad ON so.party_id = ad.party_id AND ad.type = 'shipping'
|
|
-- Zahlungsart
|
|
LEFT JOIN payment_method pm ON so.payment_method_id = pm.id
|
|
-- Bestellpositionen und Allokationen
|
|
LEFT JOIN sales_order_line sol ON so.id = sol.sales_order_id
|
|
LEFT JOIN sales_order_line_lot_allocation a ON sol.id = a.sales_order_line_id
|
|
-- Produkte (nur aktive)
|
|
LEFT JOIN product p ON a.product_id = p.id AND p.status = 'active'
|
|
|
|
WHERE so.external_ref = :bestellnummer
|
|
GROUP BY so.id, ad.id, pm.id
|
|
```
|
|
|
|
## Parameter
|
|
- `:bestellnummer` - Die externe Bestellreferenz (z.B. `W123456` oder `DIR-20260329-00017`)
|
|
|
|
## Produkt-Mapping
|
|
|
|
| Excel-Feld | Produkt-ID | SKU | Name | Status |
|
|
|------------|------------|-----|------|--------|
|
|
| `#_ChagaFlaschen` | 8 | `CHAGA` | Chaga Extrakt Tinktur 50 ml | 100% rein | aktiv |
|
|
| `#_ReishiFlaschen` | 5 | `003.01` | Reishi Extrakt Tinktur 50 ml | 100% rein | aktiv |
|
|
| `#_ShiitakeFlaschen` | 9 | `SHIITAKE` | Shiitake Extrakt Tinktur 50 ml | 100% rein | aktiv |
|
|
| `#_LionsManeFlaschen` | 6 | `005.02` | Lion's Mane Extrakt Tinktur 50 ml | 100% rein | aktiv |
|
|
|
|
**Ignoriert:** Produkt-ID 7 (`LIONSMANE`) - Status: inaktiv
|
|
|
|
## Feld-Erklärungen
|
|
|
|
### Bestellinformationen
|
|
- `Bestellnummer` - Eindeutige Bestellreferenz (Wix: BestellungNr, Direktverkauf: DIR-...)
|
|
- `Bestelldatum` - ISO 8601 Format: `YYYY-MM-DDTHH:MM:SS`
|
|
- `Versanddatum` - ISO Date Format: `YYYY-MM-DD` (automatisch berechnet als nächster Arbeitstag)
|
|
|
|
### Kundenadresse
|
|
- Alle Felder aus der Lieferadresse (`type = 'shipping'`)
|
|
- Leere Werte werden als leere Strings zurückgegeben
|
|
|
|
### Zahlungsinformationen
|
|
- `Zahlungsart` - Interner Code aus `payment_method` (z.B. `twint`, `bank_transfer`, `card`, `pickup`)
|
|
- Beträge mit 2 Dezimalstellen, NULL wird zu 0
|
|
|
|
### Produktzählungen
|
|
- Summe der allokierten Mengen pro Produkt
|
|
- Nur aktive Produkte (`status = 'active'`)
|
|
- NULL wird zu 0
|
|
|
|
## Beispieldaten
|
|
|
|
### Input
|
|
```
|
|
Bestellnummer: "W123456"
|
|
```
|
|
|
|
### Output
|
|
```json
|
|
{
|
|
"Bestellnummer": "W123456",
|
|
"Bestelldatum": "2026-04-06T14:30:00",
|
|
"Versanddatum": "2026-04-07",
|
|
"Vorname": "Max",
|
|
"Nachname": "Mustermann",
|
|
"Strasse": "Musterstrasse",
|
|
"Hausnummer": "123",
|
|
"PLZ": "8000",
|
|
"Stadt": "Zürich",
|
|
"Land": "Schweiz",
|
|
"Zahlungsart": "twint",
|
|
"Gesamtbetrag_netto": 85.00,
|
|
"Versandkosten": 5.90,
|
|
"Gesamtbetrag_brutto": 100.00,
|
|
"Rabatt": 0.00,
|
|
"#_ChagaFlaschen": 2,
|
|
"#_ReishiFlaschen": 1,
|
|
"#_ShiitakeFlaschen": 0,
|
|
"#_LionsManeFlaschen": 1
|
|
}
|
|
```
|
|
|
|
## Fehlerbehandlung
|
|
|
|
### Keine Bestellung gefunden
|
|
```json
|
|
{
|
|
"Bestellnummer": "W123456",
|
|
"Bestelldatum": "",
|
|
"Versanddatum": "",
|
|
"Vorname": "",
|
|
"Nachname": "",
|
|
"Strasse": "",
|
|
"Hausnummer": "",
|
|
"PLZ": "",
|
|
"Stadt": "",
|
|
"Land": "",
|
|
"Zahlungsart": "",
|
|
"Gesamtbetrag_netto": 0,
|
|
"Versandkosten": 0,
|
|
"Gesamtbetrag_brutto": 0,
|
|
"Rabatt": 0,
|
|
"#_ChagaFlaschen": 0,
|
|
"#_ReishiFlaschen": 0,
|
|
"#_ShiitakeFlaschen": 0,
|
|
"#_LionsManeFlaschen": 0
|
|
}
|
|
```
|
|
|
|
### Keine Produkt-Allokationen
|
|
- Alle Produktzählungen sind 0
|
|
- Andere Felder sind normal gefüllt
|
|
|
|
## Integration in n8n Flow
|
|
|
|
### Flow-Ablauf
|
|
1. **Webhook Node**: Empfängt `Bestellnummer` vom ERP
|
|
2. **Postgres Node**: Führt diese Query mit `:bestellnummer = $json.Bestellnummer` aus
|
|
3. **Excel Node**: Schreibt das Ergebnis in die Excel-Datei
|
|
4. **Response Node**: Optional - Bestätigung senden
|
|
|
|
### Query Parameters in n8n
|
|
```
|
|
Query: (siehe oben)
|
|
Query Values:
|
|
bestellnummer: {{ $json.Bestellnummer }}
|
|
Operation: Select
|
|
```
|
|
|
|
## Technische Hinweise
|
|
|
|
### Performance
|
|
- Query verwendet JOINs auf indizierten Spalten
|
|
- Gruppierung ist effizient für einzelne Bestellungen
|
|
- `COALESCE` verhindert NULL-Werte für Excel-Kompatibilität
|
|
|
|
### Datum-Logik
|
|
- `shipping_date` wird automatisch via Trigger berechnet
|
|
- Wochenend-Logik: Freitag → Montag, Samstag → Montag, Sonntag → Montag
|
|
- Keine Feiertags-Logik in Phase 1
|
|
|
|
### Schema-Konsistenz
|
|
- Alle Tabellen existieren nach Migration 0007
|
|
- `shipping_date` kann NULL sein (für sehr alte Bestellungen)
|
|
- Produkt-IDs sind statisch in der aktuellen DB
|
|
|
|
## Testing
|
|
|
|
### Test Query
|
|
```sql
|
|
-- Test mit existierender Bestellung
|
|
SELECT * FROM sales_order WHERE external_ref LIKE 'W%' OR external_ref LIKE 'DIR-%' LIMIT 5;
|
|
|
|
-- Test Query mit konkreter Bestellnummer
|
|
-- [Hier Query einfügen und :bestellnummer ersetzen]
|
|
```
|
|
|
|
### Expected Results
|
|
- Eine Zeile pro Bestellung
|
|
- Alle Felder gefüllt oder leere Strings/0
|
|
- Produktzählungen als Ganzzahlen |