Files
MyClub/eshop/ESHOP_IMPLEMENTATION_PLAN.md
T
Tomas Dvorak dfc079288f hot fix #1
2026-01-26 08:13:18 +01:00

349 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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.