Skip to content

Nyitott katalógus – admin API (igények, tételek, árlista)

Ez a dokumentum a teljes / nyitott katalógus admin oldalán elérhető REST API-t írja le. Két fő prefix:

PrefixSzerep
/api/v1/quotesIgények (nyitott sáv), szerződés Excel import, scope meta, nyitott összesítő
/api/v1/catalogKatalógus sorok keresése, CRUD, delta ár import, facet regiszter

Integration source of truth: OpenAPI (openapi.json / Redoc). Eltérés esetén az OpenAPI az irányadó. OpenAPI tag-ek: quotes, catalog.

Admin UI (referencia):

FeladatMenü / URL
Beérkező árajánlatkérésAdmin → Árajánlat → Nyitott igények/admin?tab=quote-open-requests
Katalógus tételek, árlistaAdmin → Árajánlat → Katalógus — nyitott / zárt scope alatt
MegrendelésekAdmin → Árajánlat → Megrendelések/admin?tab=quote-open-orders

Kapcsolódó kód (áttekintés):

TerületFő fájlok
Quote routersrc/modules/quote/router.py
Katalógus RESTsrc/modules/quote/catalog_router.py
Nyitott sáv adminsrc/modules/quote/open_lane_admin.py
Import joboksrc/modules/quote/catalog_import_jobs.py

Kapcsolódó auth: 01-auth-jwt.md.


Hitelesítés és tenant

Minden végpont JWT-t igényel: Authorization: Bearer <token>.

SzerepkörOlvasás (GET)Módosítás (POST/PATCH/PUT/DELETE)
VIEWERIgen (lista, admin view)Nem
EDITOR, TENANT_ADMINIgenIgen
SYSTEM_ADMINIgenIgen; X-Tenant-ID headerrel más tenant adatai is

A tenant_id a JWT-ből jön; SYSTEM_ADMIN felülírhatja X-Tenant-ID-vel (ugyanaz a minta, mint a Booking modulnál).


1. Beérkező árajánlatkérés (nyitott sáv)

A nyitott katalógus widgetből beküldött igények az admin Nyitott igények listában jelennek meg. Az ügyintéző egy oldalon látja a megrendelő adatait és az áras ajánlattáblázatot (ugyanaz a modell, mint az ügyfél „Ajánlatom” fülén).

GET /api/v1/quotes/open-lane-requests

Beküldött nyitott katalógus igények listája.

Query: limit (default 200, max 500).

Válasz: { "items": [ … ] } — minden sor tartalmazza pl. a beküldés idejét, megrendelő nevét/e-mailjét, tételszámot, nettó összeget, állapotot, request_id-t.

Szerepkör: VIEWER+.

GET /api/v1/quotes/requests/{request_id}/open-lane-admin-view

Egy igény teljes admin modellje: megrendelő blokk + sorok árakkal (megnevezés, db, egységár, sor nettó, összesen).

Szerepkör: VIEWER+.

PATCH /api/v1/quotes/requests/{request_id}/open-lane-draft

Mentés: megrendelő adatok és/vagy tételsorok módosítása.

Request body (részleges):

json
{
  "customer": {
    "name": "Kiss János",
    "email": "janos@example.com",
    "phone": "+36…"
  },
  "line_items": [  ],
  "line_ops": [  ]
}
  • customer: opcionális részleges patch.
  • line_items: teljes sorlista felülírás (admin táblázat állapota).
  • line_ops: strukturált sor-műveletek (pl. csere, törlés) — a nyitott sáv domain logikája szerint.

Válasz: frissített admin view modell.

Szerepkör: EDITOR+.

POST /api/v1/quotes/requests/{request_id}/open-lane-send

Árajánlat kiküldése e-mailben a megrendelőnek.

Request body:

json
{
  "to": "janos@example.com",
  "subject": "Árajánlat – …",
  "dry_run": false,
  "customer": {  },
  "line_items": [  ],
  "staff_note_hu": "…",
  "delivery_details_hu": "…"
}
  • dry_run: true esetén csak HTML előnézet — nem megy ki levél.
  • Ha to / subject hiányzik, a backend a megrendelő adataiból tölti.

Szerepkör: EDITOR+.

Flow: igény → szerkesztés → kiküldés

  1. Login – POST /auth/login → JWT.
  2. Lista – GET /api/v1/quotes/open-lane-requests.
  3. Részletek – GET …/requests/{id}/open-lane-admin-view.
  4. Szerkesztés – PATCH …/open-lane-draft (db, termékcsere, új sor).
  5. Küldés – POST …/open-lane-send (dry_run: true előnézethez).

Python példa – nyitott igény lista

python
import requests

BASE_URL = "https://<your-api-host>"
headers = {"Authorization": f"Bearer {JWT}"}

r = requests.get(
    f"{BASE_URL}/api/v1/quotes/open-lane-requests",
    headers=headers,
    params={"limit": 50},
)
for row in r.json().get("items", []):
    print(row.get("request_id"), row.get("customer_name"), row.get("total_net_hu"))

2. Árajánlati tételek – termék felzültés és szerkesztés

A katalógus minden sora SKU (catalog_item_id), megnevezés (title_hu), leírás (description) és facets JSON mezőkből áll. A nyitott katalógus widget és a gather/keresés az LLM terméktulajdonság mezőt használja a releváns termék kiválasztásához.

Facets mezők (fontosabb)

Facet kulcsJelentés
llm_termektulajdonsagLLM-nek szánt tulajdonság-leírás (max ~2000 karakter) — felzültés / kereshetőség
rovid_leirasRövid, emberi leírás (max ~800 karakter)
tetel_tipusmunka | anyag | szolgaltatas | egyeb
unit_codeMértékegység (pl. db, m)
unit_price_netNettó egységár (string, pl. "1950")
vat_keyÁFA kulcs (pl. "27")
brandMárka (opcionális)
catalog_scope_idZárt scope azonosító; nyitott katalógusnál nincs (scope nélküli sor)

A description mező tipikusan: llm_termektulajdonsag + újsor + rovid_leiras (ugyanaz, mint az Excel import és az admin űrlap mentése).

Katalógus sorok lapozott keresése.

Query (lényeg):

ParamLeírás
qSzöveg (cím / leírás ILIKE)
facetIsmételhető: facet=kulcs=érték
limitOldalméret (max 50)
after_title_hu, after_idKeyset lapozás
open_catalog_onlytrue → csak nyitott (scope nélküli) sorok
include_inactivetrue → inaktív sorok is

Válasz: { "items", "has_next", "next_after_title_hu", "next_after_id", "limit" }.

GET /api/v1/catalog/items/

Egy sor teljes adatai (staff).

POST /api/v1/catalog/items

Új katalógus sor.

Request body:

json
{
  "catalog_item_id": "SKU-001",
  "title_hu": "Csillárkapcsoló fehér",
  "description": "Fehér csillárkapcsoló, 10A\nRövid leírás…",
  "facets": {
    "llm_termektulajdonsag": "Fehér csillárkapcsoló, 10A, fali szerelés",
    "rovid_leiras": "Standard fehér kapcsoló",
    "tetel_tipus": "anyag",
    "unit_code": "db",
    "unit_price_net": "1950",
    "vat_key": "27"
  },
  "active": true
}

PATCH /api/v1/catalog/items/

Részleges frissítés: title_hu, description, facets, active.

Példa – csak LLM tulajdonság frissítése:

json
{
  "facets": {
    "llm_termektulajdonsag": "Fehér csillárkapcsoló, 10A, IP20, fali"
  }
}

A facets patch merge viselkedésű a szolgáltatásban: a megadott kulcsok frissülnek, a többi megmarad.

POST /api/v1/catalog/items/bulk

Tömeges import (max 200 sor / kérés). Body: { "items": [ … ], "continue_on_error": false }.

Szerepkör (catalog CRUD): EDITOR+ (_staff).


3. Árlista és tételek módosítása (tömeges)

Szerződés Excel import (teljes / scope)

Nagy katalógus (millió+ tétel) tipikusan Excel szerződés sablonnal töltődik fel.

EndpointMethodLeírás
/api/v1/quotes/catalog/contract-templateGETÜres sablon letöltése (.xlsx)
/api/v1/quotes/catalog/import/startPOSTHáttér import (multipart: file, opc. catalog_scope_id, dry_run) → job_id
/api/v1/quotes/catalog/import/statusGETJob poll (job_id)
/api/v1/quotes/catalog/importPOSTSzinkron import (script / teszt)
  • catalog_scope_id hiányzik → nyitott (teljes) katalógus sáv.
  • catalog_scope_id megadva → zárt scope import (lásd GET /api/v1/quotes/catalog/scopes).

GET /api/v1/quotes/catalog/open-summary — nyitott katalógus: item_count, last_import_at.

GET /api/v1/quotes/catalog/open/import-batches — import batch azonosítók listája.

Delta ár import (csak árváltozás)

Meglévő SKU-k nettó egységárának frissítése JSON-ból — teljes Excel újratöltés nélkül.

POST /api/v1/catalog/import-price-delta

json
{
  "dry_run": true,
  "items": [
    { "catalog_item_id": "SKU-001", "unit_price_net": "2100" },
    { "catalog_item_id": "SKU-002", "unit_price_net": "890" }
  ]
}

Válasz:

json
{
  "ok": true,
  "dry_run": true,
  "updated_count": 2,
  "missing_count": 0,
  "missing_skus": []
}
  • dry_run: true → szimuláció, DB nem változik.
  • missing_skus: nem található SKU-k listája.

Max 500 sor / kérés.

Python példa – delta ár (dry run)

python
import requests

BASE_URL = "https://<your-api-host>"
headers = {"Authorization": f"Bearer {JWT}", "Content-Type": "application/json"}

body = {
    "dry_run": True,
    "items": [
        {"catalog_item_id": "ABC-123", "unit_price_net": "15000"},
    ],
}
r = requests.post(
    f"{BASE_URL}/api/v1/catalog/import-price-delta",
    headers=headers,
    json=body,
)
print(r.json())

4. Megrendelések (nyitott sáv, rövid)

Az ügyfél a widgetben Megrendelem után megrendelés keletkezik.

EndpointMethodLeírás
/api/v1/quotes/open-lane-ordersGETMegrendelések listája
/api/v1/quotes/requests/{request_id}/open-lane-orderPATCHdelivered: true — kiszállítva jelölés

Admin UI: /admin?tab=quote-open-orders.


Zárt vs nyitott katalógus (meta)

Nyitott (teljes)Zárt scope
Scope mezőNincs catalog_scope_id a facetbenVan catalog_scope_id
Importcatalog_scope_id nélkülcatalog_scope_id=<scope>
Keresés szűrőopen_catalog_only=truefacet=catalog_scope_id=<scope>
Scope CRUD/api/v1/quotes/catalog/scopes

A nyitott katalógus public widget tokenje és a zárt katalógus tokenje külön admin fülön kezelhető — lásd 52-admin-public-widget-tokens.md és a quote public token admin UI-t.


További információ