This commit is contained in:
Tomas Dvorak
2026-01-26 08:13:18 +01:00
parent aa036b6550
commit dfc079288f
505 changed files with 95755 additions and 5712 deletions
+348
View File
@@ -0,0 +1,348 @@
# MyClub Eshop Implementační plán
> Cíl: přidat volitelný MyClub eshop jako samostatný (ale integrovaný) stack vlastní backend + frontend, napojený na stávající MyClub uživatele a admin, s podporou Stripe plateb, Packeta (Zásilkovna) dopravy a DeepSeek AI podpory. Vše řízené přes `.env` a Docker Compose.
---
## 1. Architektura a základní principy
- **Samostatný eshop stack**
- `eshop-backend` Go/Gin služba, vlastní API prefix (např. `/api/v1/eshop`), sdílí DB a auth s hlavním backendem.
- `eshop-frontend` React/TSX (Chakra UI + ClubThemeContext), vlastní doména/subdoména (např. `shop.klub.cz`).
- V docker-compose jako dva nové servisy, spouštěné jen pokud `ESHOP_ENABLED=true`.
- **Sdílené jádro s MyClub**
- Sdílená databáze (PostgreSQL) nové tabulky s prefixem `eshop_`.
- Sdílený users / role systém (admin/editor/uživatel) žádné duplikování účtů.
- Admin správa eshopu v existujícím `/admin` (nové sekce „Eshop“ / „Produkty“, „Objednávky“, „Nastavení eshopu“).
- **UI/UX**
- Světlý + tmavý režim, jednoduché, mobilfirst.
- Barvy z klubového theme (z inicializačního Setupu) eshop z něj dědí, ale může mít drobné odchylky (např. CTA barvy).
- **Bezpečnost**
- Žádné ukládání karetních údajů (vše přes Stripe).
- Sdílená JWT/session autentizace mezi doménami (cookies `Domain=.example.cz`).
- CORS a CSRF nastavené tak, aby podporovaly hlavní web + eshop subdoménu.
---
## 2. Konfigurace přes .env
### 2.1 Klíčové flagy
- `ESHOP_ENABLED=true|false`
- `true` → Docker Compose spustí i eshop backend/frontend, setup přidá eshop doménu a nastavení.
- `false` → běží pouze hlavní MyClub (aktuální chování).
- Domény & URL
- `FRONTEND_URL=https://www.klub.cz` (stávající)
- `API_URL=https://api.klub.cz` (stávající)
- `ESHOP_FRONTEND_URL=https://shop.klub.cz`
- `ESHOP_API_URL=https://eshop-api.klub.cz` *nebo* `https://api.klub.cz/eshop` (dle zvoleného nasazení)
- Porty pro lokální vývoj
- `ESHOP_FRONTEND_PORT=3100`
- `ESHOP_BACKEND_PORT=8082`
### 2.2 Stripe
- `STRIPE_SECRET_KEY=sk_live_...`
- `STRIPE_PUBLISHABLE_KEY=pk_live_...`
- `STRIPE_WEBHOOK_SECRET=whsec_...`
- `STRIPE_CURRENCY=CZK`
- `STRIPE_SUCCESS_URL=${ESHOP_FRONTEND_URL}/objednavka/uspech`
- `STRIPE_CANCEL_URL=${ESHOP_FRONTEND_URL}/kosik`
### 2.3 DeepSeek (AI podpora)
- `DEEPSEEK_ENABLED=true|false`
- `DEEPSEEK_API_KEY=...`
- `DEEPSEEK_MODEL=deepseek-chat`
- `DEEPSEEK_API_BASE=https://api.deepseek.com`
### 2.4 Packeta / Zásilkovna
- `PACKETA_API_PASSWORD=...` (hlavní API heslo pro REST/XML)
- `PACKETA_WIDGET_API_KEY=...` (16znakový klíč pro widget)
- `PACKETA_ESHP_NAME=MyClubEshop`
- `PACKETA_ENV=production|test` (logika: v test režimu umožnit vytvářet zásilky jen v interním módu)
---
## 3. Docker Compose a Makefile
### 3.1 Nové servisy v docker-compose
- `eshop-backend`
- build: `./eshop/backend`
- env: sdílí DB proměnné s hlavním backendem (`DB_HOST`, `DB_USER`, `DB_PASS`, `DB_NAME`), plus `ESHOP_*`, `STRIPE_*`, `PACKETA_*`, `DEEPSEEK_*`.
- port: `${ESHOP_BACKEND_PORT}:8080` (interní port 8080 jako u hlavního backendu).
- `eshop-frontend`
- build: `./eshop/frontend`
- env: `ESHOP_API_URL`, `ESHOP_FRONTEND_URL`, `NODE_ENV`, atd.
- port: `${ESHOP_FRONTEND_PORT}:3000`.
### 3.2 Podmíněné spouštění
- V `Makefile` upravit cíle (např. `docker-up`):
- Shell podmínka: pokud `ESHOP_ENABLED=true`, použít `docker compose -f docker-compose.yml -f docker-compose.eshop.yml up`; jinak jen základní `docker-compose.yml`.
- Alternativně: jeden compose soubor, ale cíle `docker-up` vs `docker-up-with-eshop` (flag řízený z Makefile).
---
## 4. Databázový model eshopu
Použít GORM modely v novém modulu, např. `internal/models/eshop/...`.
- **Product** (`eshop_products`)
- `id`, `slug`, `name`, `description_html`, `short_description`, `price`, `currency`, `vat_rate`, `active`, `stock_mode` (finite/unlimited), `default_image_url`, `gallery_urls`, `tags`, `metadata`.
- **ProductCategory** (`eshop_product_categories`)
- hierarchie kategorií pro filtraci (dresy, fan merchandise, permanentky...).
- **ProductVariant** (`eshop_product_variants`)
- velikosti/barvy, vlastní `sku`, `stock_qty`, `barcode` (volitelně), `image_url`.
- **Cart / CartItem** (`eshop_carts`, `eshop_cart_items`)
- vázané na `user_id` nebo anonymní session (`session_token`).
- **Order / OrderItem** (`eshop_orders`, `eshop_order_items`)
- stav: `new`, `awaiting_payment`, `paid`, `cancelled`, `refunded`, `ready_to_ship`, `shipped`, `delivered`.
- vazba na Packeta/Carrier: `shipping_method`, `packeta_point_id`/`address_id`, `tracking_number`.
- **Payment** (`eshop_payments`)
- Stripe `payment_intent_id`, `status`, `amount`, `currency`, `refund_status`, `raw_payload` (JSON pro debug, GDPRsafe).
- **ShippingLabel** (`eshop_shipping_labels`)
- Packeta `packet_id`, `label_url` / binární uložiště, historie statusů.
- **EshopSettings** (`eshop_settings`)
- `default_currency`, `supported_currencies`, `default_country`, `shipping_options`, `terms_url`, `returns_policy_url`, `support_email`, `support_phone`, atd.
---
## 5. Backend API a integrace s MyClub
### 5.1 Struktura backendu
- Nový modul/složka: `internal/controllers/eshop`, `internal/services/eshop`, `internal/routes/eshop_routes.go`.
- Registrace rout v `routes.go`, ale oddělený API prefix `/api/v1/eshop`.
- Middleware:
- `JWTOptional` pro veřejné eshop stránky (checkout, košík, historie objednávek pro přihlášené).
- Role guardy pro admin API (jen admin/editor s právem eshop).
### 5.2 Veřejné API (zkrácený přehled)
- Produkty
- `GET /api/v1/eshop/products` list s filtrem (kategorie, dostupnost, fulltext).
- `GET /api/v1/eshop/products/:slug` detail.
- Košík
- `GET /api/v1/eshop/cart` ze session nebo user_id.
- `POST /api/v1/eshop/cart/items` přidání položky.
- `PATCH /api/v1/eshop/cart/items/:id` změna množství/varianty.
- `DELETE /api/v1/eshop/cart/items/:id`.
- Checkout & platby (Stripe)
- `POST /api/v1/eshop/checkout` vytvoření draft objednávky + PaymentIntent (viz kapitola Stripe).
- `GET /api/v1/eshop/orders/:id` detail objednávky pro daného uživatele.
- Doprava (Packeta)
- `GET /api/v1/eshop/shipping/options` dostupné způsoby dopravy.
- `GET /api/v1/eshop/shipping/packeta/widget-config` vrací `PACKETA_WIDGET_API_KEY` a další volby pro widget.
- DeepSeek podpora
- `POST /api/v1/eshop/support/chat/stream` SSE/WebSocket proxy na DeepSeek (viz níže).
### 5.3 Admin API
- Produkty & kategorie
- CRUD endpoints pro produkty, varianty a kategorie.
- Objednávky
- List/filtering podle stavu, data, zákazníka.
- Akce: změna stavu, přidání poznámky, rušení/refund.
- Nastavení eshopu
- Stripe, Packeta, texty emailů a obchodní podmínky.
---
## 6. Autentizace a napojení účtů
- Použít existující `users` tabulku a JWT/session middleware.
- Upravit nastavení cookies tak, aby `Domain=.example.cz` → token platí pro hlavní web i `shop.example.cz`.
- CORS policy: přidat eshop frontend origin mezi povolené.
- V eshop frontendu používat stejný mechanismus přihlášení (sdílené služby/axios klient nebo lehké proxy).
---
## 7. Frontend veřejný eshop (TSX)
### 7.1 Technologie
- React 18 + TypeScript + Chakra UI, opět využít `ClubThemeContext` (stejný design systém jako hlavní frontend).
- Routing: `react-router` (oddělené entrypointy v rámci `eshop/frontend`).
### 7.2 Stránky
- Domovská stránka eshopu výběr kategorií, bestsellery, CTA.
- Katalog produktů (grid, filtry, stránkování).
- Detail produktu fotogalerie, varianty (velikost/barva), doporučené produkty.
- Košík přehled položek, úprava množství, mezisoučet.
- Checkout kroky:
1. Fakturační údaje
2. Doprava (Packeta widget / jiní dopravci)
3. Shrnutí + platba (Stripe)
- Potvrzení objednávky.
- Můj účet → historie objednávek (pro přihlášené MyClub uživatele).
### 7.3 UX detaily
- Plná responzivita (mobil, tablet, desktop).
- Dark mode připnutý na globální přepínač (stejný jako u hlavního webu).
- Konsistentní komponenty (buttony, formuláře, toasty) s adminem.
---
## 8. Frontend admin část eshopu
- V existujícím admin SPA přidat navigační kategorii „Eshop“:
- **Produkty** CRUD, nahrávání obrázků, varianty.
- **Objednávky** tabulka, detail, timeline stavu, link na Packeta štítky.
- **Přehledy** dashboard s grafy (tržby/den, počet objednávek, úspěšnost plateb, rozdělení dopravců).
- **Nastavení eshopu** měna, Stripe, Packeta, email šablony.
- Využít existující komponenty (tabulky, filtry, grafy) používané v jiných admin modulech.
---
## 9. Stripe platební tok
1. **Checkout** (frontend)
- Uživatel vyplní adresu, zvolí dopravu a souhlasí s podmínkami.
- Frontend volá `POST /api/v1/eshop/checkout` s obsahem košíku a dopravou.
2. **Backend**
- Zkontroluje ceny/propočítá dopravu.
- Vytvoří **Stripe PaymentIntent** (`amount`, `currency`, `metadata` s `order_id`).
- V DB uloží draft objednávku se stavem `awaiting_payment`.
- Vrátí `client_secret` pro frontend.
3. **Frontend**
- Použije Stripe Elements / `stripe-js` k potvrzení platby.
4. **Webhook** (backend)
- Endpoint např. `/api/v1/eshop/stripe/webhook` (mimo auth, chráněn `STRIPE_WEBHOOK_SECRET`).
- Reaguje na eventy `payment_intent.succeeded`, `payment_intent.payment_failed`, `charge.refunded`.
- Upraví stav objednávky (`paid`, `cancelled`, `refunded`).
5. **Email & Packeta**
- Po `paid`:
- poslat email zákazníkovi + adminovi (použít existující `pkg/email`).
- příprava vytvoření Packeta zásilky (viz níže).
---
## 10. Packeta / Zásilkovna doprava (✔ hotovo - MVP)
Vychází z `eshop/packeta.md`.
### 10.1 Frontend widget
- Na stránce checkoutu:
- ✔ načíst `<script src="https://widget.packeta.com/v6/www/js/library.js"></script>` (lazy load přes `useEffect`).
- ✔ na výběr způsobu dopravy „Výdejní místo Packeta“ otevřít widget přes `Packeta.Widget.pick(...)`.
- ✔ výsledek (objekt `point`) uložit do checkout state a poslat na backend (`addressId`, `name`, `country`, atd.).
### 10.2 Backend vytvoření zásilky
- Po úspěšné platbě (nebo po manuálním potvrzení objednávky):
- ✔ Vytvořit XML payload `createPacket` (viz `packeta.md`) `PacketaService.CreatePacket`.
- ✔ Poslat POST na `https://www.zasilkovna.cz/api/rest`.
- ✔ Uložit `packetId` a případně generovat PDF štítek přes `packetLabelPdf` `PacketaService.GetPacketLabel`.
- ✔ Endpoint `/api/v1/eshop/shipping/labels/:packet_id` pro stažení PDF.
- ⬜ Pravidelný cron (např. background job v Go):
- `packetStatus` / `packetTracking` → aktualizovat stav objednávky.
- ⬜ V adminu zobrazit log posledních stavů, link na stažení štítku.
---
## 11. DeepSeek AI zákaznická podpora
- Backend endpoint: `POST /api/v1/eshop/support/chat/stream`
- Auth: volitelně JWT (výhoda známe uživatele/jazyk, můžeme dotáhnout jeho objednávky).
- Vstup: zprávy konverzace + kontext (parametry eshopu, aktuální objednávky atd.).
- Backend zavolá DeepSeek API s modelem `deepseek-chat` a `stream=true`.
- Přeposílá stream (SSE/WebSocket) na frontend.
- System prompt uložit v repu jako Markdown (soubor vedle tohoto plánu) **`DeepSeekSupportPrompt.md`** (vytvořený v tomto kroku).
- AI odpovídá česky, stručně, s možností přepnout do angličtiny, pokud je dotaz v AJ.
---
## 12. Emaily a notifikace
- Využít existující emailový systém (SMTP konfigurace už je v MyClub).
- Nové šablony:
- Potvrzení objednávky (CZ, s rekapitulací a odkazem na detail).
- Informace o platbě (zaplaceno/neúspěch).
- Informace o odeslání (včetně Packeta tracking linku).
- Informace o doručení/uzavření.
---
## 13. Dvoukrokový Setup
1. **Hlavní MyClub Setup** (stávající `/setup`)
- Klubové údaje, barvy, logo, doména.
2. **Eshop Setup** (nový krok/route, aktivní jen pokud `ESHOP_ENABLED=true`)
- URL eshopu (`ESHOP_FRONTEND_URL`, `ESHOP_API_URL` předvyplnit z hlavního URL + subdomény).
- Default měna, země, jazyk.
- Základní texty (obchodní podmínky URL, kontakt na podporu).
- Volba povolených dopravců (Packeta on/off, typy).
- Eshop Setup přebírá klubové informace (název, logo, barvy) jako výchozí.
---
## 14. Bezpečnost a performance
- Middleware pro ratelimit u eshop API (checkout, platby, podpora chat).
- Sanitizace všech vstupů (hlavně HTML popisy produktů a AI odpovědi DOMPurify na frontendu, validace na backendu).
- Logování citlivých dat minimalizovat (žádné celé adresy/karty v debug logu).
- Použít existující httpclient/circuitbreaker vrstvy z MyClub pro Packeta a DeepSeek.
---
## 15. Fáze implementace
1. **Infrastruktura**
- Nové .env proměnné, docker-compose.eshop.yml, Makefile logika.
2. **DB a backend jádro**
- Migrace tabulek `eshop_*`, základní GORM modely.
- Produkty, košík, objednávky (bez plateb/dopravy).
3. **Eshop frontend (MVP)**
- Katalog, detail, košík, jednoduchý checkout bez Stripe (např. platba převodem jako první krok).
4. **Stripe integrace**
- PaymentIntent, webhooky, stav objednávek.
5. **Packeta integrace**
- Widget na checkoutu, backend `createPacket`, štítky, cron pro statusy.
6. **Admin eshop modul**
- Produkty, objednávky, přehledy.
7. **DeepSeek podpora**
- Backend proxy + frontend chat widget, ladění promptu.
8. **Hardening a testy**
- E2E testy checkoutu, zátěžové testy API, bezpečnostní audit.