# Pakajo Dashboard · Backend-Integration für Entwickler

Stand: 10.10.2026 · Mockup-Build 2026-10-10-47

Dieses Dokument beschreibt, **wo das Frontend-Mockup an das Pakajo-Backend andockt**, welche Module wem gehören und welche Datenverträge gelten. Ziel: Die Entwickler tauschen **eine Datei** (den Adapter) gegen echte Endpunkte – die Module (Einzelversand, Massenversand, Versandregeln, Pickup, Abo, …) bleiben unverändert.

---

## 1. Architektur: `window.PakajoBackend` (Adapter)

Der Adapter liegt im Mockup als eigener Script-Block (`PAKAJO BACKEND ADAPTER`, direkt vor den App-Modulen). Hinter jeder Funktion stehen heute Mock-Daten (localStorage, Demo-Listen). Die Module rufen **nur** `PakajoBackend.*` auf.

| Namespace | Funktionen | Produktion (Vorschlag) |
|---|---|---|
| `config` | `vatRate()`, `currency()`, `pointValueEur()`, `minTopupEur()` | `GET /config` |
| `countries` | `iso2(any)`, `iso3(iso2)`, `name(iso2)`, `flag(iso2)`, `label(iso2)`, `isEU(iso2)`, `eu()`, `list()` | statisch / `GET /countries` |
| `carriers` | `all()`, `byId(id)`, `byName(name)`, `idOf(x)`, `forScreen()`, `forCountry(iso2)` → `{local, global, all}`, `bulkNames()` | `GET /carriers?country=ES` |
| `products` | `all()` (Codes 1–7), `byCode(code)`, `codeFromText(txt)`, `pickup(mode)` (pickup/dropoff/retoure) | `GET /products`, `GET /products/pickup` |
| `pricing` | `quote(ctx)` → `{carrierId, net, vat, gross, service, days}`, `quoteAll(ctx, list)`, `fmt(n)` | `POST /quote` |
| `customers` | `list()`, `get(mid)`, `active()`, `save(mid, data)` | `GET/PUT /customers/{mid}` |
| `users` | `list()`, `current()` | `GET /users`, `GET /me` |
| `subscriptions` | `plans()`, `features(plan)`, `active()`, `offerGroup(mid)` | `GET /subscriptions`, Angebotsgruppen |
| `billing` | `get(mid)`, `invoices()` (ESN-Daten) | `GET /billing/{mid}`, `GET /invoices` |
| `shipments` | `orders()`, `imported()` | `GET /orders`, `POST /shipments/import` |
| `tracking` | `events(nr)` | KI-Tracking (vorhanden) |
| `returns` | `list()` | Retourenfunktion (vorhanden) |
| `orders` | `shopOrders()`, `articles()` | Shop-/Marktplatz, Artikel (vorhanden) |
| `performance` | `query(sql)` | SQL-Editor → Frontend |
| `rules` | `list()`, `save(list)`, `aiSuggestions()` | `GET/PUT /rules`, KI-Vorschläge |
| `glocal` | `countries()` | Produktgruppe Glocal |
| `claims` | `tickets()`, `webhook(ev)` | Bitrix24 (ONTASKADD / ONTASKUPDATE / ONTASKCOMMENTADD) |
| `addressbook`, `boxPresets`, `branding`, `points`, `pricingTool`, `currency`, `integrations`, `apiDocs`, `chatbot`, `profile`, `security` | siehe Adapter | |
| `importTax(iso)` | Einfuhrsteuer je Land (CH 8,1 % / 2,6 % Drucksachen) | `GET /customs/import-tax/{iso}` |

`PakajoBackend.meta.ownership` enthält die Zuständigkeit je Modul (Backend / gemischt / Frontend) – abrufbar über `PakajoBackend.ownerOf('rules')`.

---

## 2. Zuständigkeiten je Modul

| Modul | Zuständigkeit | Hinweis |
|---|---|---|
| Versanddienste / Versandprodukte (inkl. Pickup, Drop-off, Retoure) | **Backend** | Einzige Quelle `carriers` + `products`; Frontend identifiziert Carrier über `carrierId`, nie über den Anzeigenamen |
| Kundendaten / Mandanten | **Backend** | Bestand aus dem Backend; neue Kunden per Selbstregistrierung (Master-Mandant) oder direkt im Backend (z. B. Enterprise) |
| User & Rollen, Integrationen, Profildaten (User) | **Backend** | |
| Shop-/Marktplatzbestellungen, Artikelübersicht | **Backend** | bereits vorhanden |
| KI-Tracking | **Backend** | bereits vorhanden, Frontend zeigt nur an |
| Retouren | **Backend** | bereits vorhanden, Frontend spielt aus |
| Glocal-Länder | **Backend** (Produktgruppe Glocal) | Glocal-Übersicht selbst = Landingpage (Frontend) |
| API & Doku | **Backend** | weitgehend vorhanden |
| Massenversand | gemischt | Import/Validierung/Kalkulation teilweise Backend; Zeilen tragen `data-dest`, `data-gewicht`, `data-produkt`, `data-carrier-id` |
| Versandregeln | gemischt | Regeln je Kunde; Dienste/Services aus dem Backend; Matching über ISO-2 + Produktcode |
| Versandperformance | gemischt | Versanddaten per SQL-Editor (`performance.query`) |
| Abonnements / Angebotsgruppen / Rabatte | gemischt | Darstellung Frontend, Logik Backend; Plan-Gating (`ABO_FEATURES`) muss serverseitig gespiegelt werden |
| Handelsrechnung | gemischt | aus Kundeneingaben |
| Rechnungsdaten | gemischt | aus ESN-Versanddaten |
| Reklamation / Schadensfälle | gemischt | Bitrix24-CRM (Ticket vom Service, Kunde = Mitwirkender, Webhooks) |
| Chatbot | embedded | |
| Adressbuch | Anzeige Frontend, Daten Backend | |
| Branding, Paku Points, Pricing-Tool, Multicurrency, Archivierung | gemischt | Paku Points nur Free/Bronze/Silber/Gold (nicht Enterprise) |
| Paketgrößen (Box-Presets), 2FA/Sicherheit, Registrierungs-UI | **Frontend** | |

---

## 3. Datenverträge (Mockup-Form = Zielform)

```js
// Carrier
{ id: 'tipsa', name: 'Tipsa Parcel', service: 'PRIORITY'|'STANDARD'|'AUTO', days: '2-5 d',
  maxKg: 30, basePrice: 3.75 /* netto EUR */, coverage: ['*'] | ['ES'], features: [...], screen: true, tag: 'lokal', virtual: false }

// Versandprodukt
{ code: '1'..'7', name: 'Paket mit Sendungsverfolgung', priceMod: 0.00, label: 'mit Tracking' }

// Quote-Anfrage / -Antwort
quote({ carrier: 'tipsa', iso2: 'ES', gewicht: 500 /* g */, laenge: 300, breite: 200, hoehe: 100 /* mm */,
        produkt: '2', insuranceFee: 0.99, express: false })
→ { carrierId: 'tipsa', carrier: 'Tipsa Parcel', net: 4.11, vat: 0.78, gross: 4.89, service: 'PRIORITY', days: '2-5 d' }

// Versandregel
{ id: 'R-…', name: 'Spanien → Tipsa', land: 'Spanien' | 'EU' | 'NONEU' | '', landIso: 'ES', produkt: '' | '1'..'7',
  wmin: 0, wmax: 1000 /* g */, mandant: '' | '3001', act: 'cheapest'|'carrier'|'fastest'|'service',
  carrier: 'Tipsa Parcel', carrierId: 'tipsa', service: 'STANDARD'|'PRIORITY', auto: true, active: true, ai: false, hits: 0 }

// Massenversand-Zeile (data-Attribute am <tr>)
data-nr="572640" data-dest="DE" data-gewicht="480" data-produkt="2" data-carrier-id="dhl"

// Carrier-Karte Einzelversand
data-carrier="Česká pošta" data-carrier-id="ceska" data-net="3.57" data-service="PRIORITY"
```

Konventionen: Länder **ISO 3166-1 alpha-2** als Schlüssel (`countries.iso2()` normalisiert ISO-3, Namen, Flaggen, „Stadt · Land"); Preise **netto EUR**, Brutto-Anzeige über `config.vatRate()`; Status-Werte als Enums (siehe Abschnitt 5).

---

## 4. Was im Refactoring (Build -47) bereits umgesetzt wurde

1. **Eine Carrier-Liste** (`PakajoBackend.carriers`) ersetzt sieben parallele Listen (Einzelversand, Sendungs-Dialog lokal/global, Massenversand-Dropdown, Regeln). Carrier haben IDs.
2. **Eine Preisformel** (`pricing.quote`) für Einzelversand, Sendungs-Dialog und Versandregeln – vorher drei verschiedene Formeln (unterschiedliche Preise auf Karte vs. Dialog).
3. **Länder-Normalisierung** `countries.iso2()` – Versandregeln und Massenversand matchen über ISO-2 statt über deutsche Ländernamen.
4. **Versandprodukte 1–7** aus `products` (Preis-Modifier zentral).
5. **data-Attribute** statt Textparsing: Carrier-Karten (`data-carrier-id`, `data-net`) und Massenversand-Zeilen (`data-dest`, `data-gewicht`, `data-produkt`, `data-carrier-id`).
6. **MwSt-Satz** aus `config.vatRate()`.
7. Pickup/Drop-off/Retoure-Produktlisten über `products.pickup(mode)` erreichbar.

---

## 5. Offene Punkte für die Produktivanbindung (Empfehlung, Priorität absteigend)

1. **Geschäftslogik ins Backend**: Abo-Gating, Mandanten-/User-Limits, Prepaid-Saldo, SEPA-Freigabe, Bronze-Testmonat, Plan-Wechsel, Prepaid-Gutschrift, Punkte-Rate/Margen, Zollsätze, Abhol-Kontingente/Füllregel. Im Mockup liegt das in localStorage (40 `pakajo-*`-Keys) und ist clientseitig manipulierbar.
2. **Sicherheit**: LLM-Keys (Anthropic/OpenAI) liegen im Browser und werden direkt aufgerufen → über das Backend proxyen. Login-Übergabe per `?selfreg=<base64>` in der URL (Name/E-Mail/Firma) → Session-Token. Tracking-Abfrage (`fetchOne`) → Backend.
3. **IDs vom Server**: Tracking-Nummern, Buchungs-Nr., Ticket-IDs, Gutschrift-IDs werden im Mockup per `Math.random()` erzeugt.
4. **Enums vereinheitlichen**: Status gemischt (`offen`, `printed`, `pending`, `abgeschlossen`, `delivered`); Plan intern `Platin`, angezeigt „Enterprise". Vorschlag: `SHIPMENT_STATUS`, `PLAN`, `PRODUCT` als zentrale Enums, Labels über i18n.
5. **Restliche Länder-Selects** (`ship-zielland` ISO-2, `screen-versand-land` ISO-3, Adressbuch/Mandant Klartext) auf ISO-2-Werte umstellen – `countries.iso2()` fängt das heute ab, sauber ist ein einheitlicher `value`.
6. **Statische Demo-Zeilen** im Massenversand (2600–2607) durch Seed-Daten aus `shipments.orders()` ersetzen; die Regel-Anwendung hat dafür noch einen Text-Fallback.
7. **Brutto/Netto- und Währungsumrechnung** (`convertCardsVat`, `convertPricesInDom`) rendern heute per MutationObserver über fertige DOM-Preise. Zielbild: Preise aus `quote()` (`net`/`gross`) direkt rendern, Observer entfernen.

---

## 6. Storage-Keys im Mockup (Mapping auf Backend)

| Key | Inhalt | Ziel |
|---|---|---|
| `pakajo-selfreg` | Konten, Logins, Session (geteilt Login ↔ Dashboard) | Auth-Service |
| `acct:<id>:…` | Namespace je Kundenkonto für alle folgenden Keys | serverseitig je Kunde |
| `pakajo-mandant-settings` | Mandanten (`MANDANTEN_DEFAULTS`) | `customers` |
| `pakajo-users` | User & Rollen | `users` |
| `pakajo-billing-<mid>` | Prepaid, Zahlungsmethode, SEPA, Gutschriften | `billing` |
| `pakajo-selected-plan:<mid>`, `pakajo-plan-since:<mid>`, `pakajo-plan-pending:<mid>` | Abo-Zustand | `subscriptions` |
| `pakajo-auftraege`, `pakajo-imported-shipments` | Aufträge/Sendungen | `shipments` |
| `pakajo-ship-rules`, `pakajo-ship-rules-ai` | Versandregeln, AI-Vorschlag-Status | `rules` |
| `pakajo-rek-tickets` | Reklamations-Tickets (Bitrix-Spiegel) | `claims` |
| `pakajo-addressbook`, `pakajo-boxpresets`, `pakajo-branding-<mid>` | Adressbuch, Paketgrößen, Branding | entsprechende Namespaces |
| `pakajo-points-<mid>`, `pakajo-pickups-<mid>` | Paku Points, Abhol-Kontingent | `points`, Pickup-Service |
| `pakajo-lang`, `pakajo-user-currency` | UI-Präferenzen | `profile` |
