- Python 68.6%
- TypeScript 30.6%
- Dockerfile 0.3%
- CSS 0.2%
- Mako 0.2%
Make the new AI schema migration idempotent by checking existing columns, indexes, and tables before creation so upgrades succeed even when parts of the schema already exist. |
||
|---|---|---|
| backend | ||
| frontend | ||
| gateway | ||
| .env.example | ||
| .gitignore | ||
| codex-ai-valuation-prompt.md | ||
| deal-finder-mvp.md | ||
| docker-compose.yml | ||
| MVP_SPEC.md | ||
| README.md | ||
Deal Finder MVP
Soukroma webova aplikace pro rucni vyhledavani podhodnocenych pocitacu a komponent na ceskych bazarech.
Zdroj pravdy
- Hlavni specifikace:
deal-finder-mvp.md - Archiv predchozi verze:
MVP_SPEC.md
Pouzite technologie
- Frontend: Next.js, React, TypeScript, Tailwind CSS, TanStack Query/Table, React Hook Form + Zod, Recharts
- Backend: FastAPI, SQLAlchemy 2, Alembic, httpx, selectolax
- Databaze: PostgreSQL
- Provoz: Docker Compose + Nginx reverse proxy
Struktura repozitare
frontend- web UIbackend- API, adaptery, scan workflow, oceneni, SMTPgateway- Nginx konfiguracedocker-compose.yml- provozni stack
Instalace a prvni spusteni
-
Vytvor konfiguraci:
cp .env.example .env -
Nastav bezpecne hodnoty:
APP_SECRETPOSTGRES_PASSWORDSESSION_SECURE_COOKIES=truev produkci pod HTTPS
-
Spust aplikaci:
APP_PORT=3017 docker compose up -d --buildPouzij libovolny volny port;
3000muze byt obsazeny jinou sluzbou. -
Otestuj healthcheck:
curl -fsS http://127.0.0.1:3017/api/health -
Otevri UI:
http://127.0.0.1:3017/login
Docker Compose provoz
Sluzby:
gateway- jediny vystaveny port na hostufrontend- Next.js aplikacebackend- FastAPI API (pri startu provadialembic upgrade head)db- PostgreSQL
Kontejnery bezici stale:
APP_PORT=3017 docker compose ps
Logy:
APP_PORT=3017 docker compose logs -f backend
Migrace databaze
Rucni migrace:
APP_PORT=3017 docker compose exec backend alembic upgrade head
Vytvoreni nove migrace:
APP_PORT=3017 docker compose run --rm -v /home/investment/DealFinder/backend:/app backend alembic revision --autogenerate -m "popis zmeny"
Reverse proxy priklad
gateway/nginx.conf smeruje:
/api/*->backend:8000- vse ostatni ->
frontend:3000
Minimalni externi reverse proxy (napr. Caddy/Nginx) ma smerovat HTTPS provoz na host port APP_PORT.
SMTP propojeni z Dockeru
Backend pouziva env promenne:
SMTP_HOST,SMTP_PORT,SMTP_USERNAME,SMTP_PASSWORD,SMTP_FROM,SMTP_TO,SMTP_STARTTLS
V Compose je nastaveno:
extra_hosts:
- "host.docker.internal:host-gateway"
Dulezite:
- SMTP naslouchajici jen na
127.0.0.1hostitele neni z kontejneru dostupne. - Bezpecnejsi varianta je naslouchat na Docker bridge IP a omezit firewall na konkretni Docker sit.
- Pokud SMTP bezi v Dockeru, preferuj sdilenou pojmenovanou Docker sit a host podle DNS jmena SMTP kontejneru.
Zalohovani a obnova PostgreSQL
Zaloha:
APP_PORT=3017 docker compose exec db pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB" > backup.sql
Obnova:
cat backup.sql | APP_PORT=3017 docker compose exec -T db psql -U "$POSTGRES_USER" "$POSTGRES_DB"
Pridani noveho bazaroveho adapteru
- Vytvor novy adapter v
backend/app/adapters/<source>.pyimplementujici:scan(max_price)fetch_listing(url)
- Pridat adapter do
ALL_ADAPTERSvbackend/app/adapters/__init__.py - Pridat fixture HTML testy v
backend/tests/fixtures+ parser test vbackend/tests/test_adapters.py - Udrzet adapterovou logiku uvnitr adapteru (bez rozptyleni selektoru po aplikaci)
Omezeni zdroju
- Adaptery pouzivaji pouze verejne dostupne stranky.
- Pri detekci blokace/CAPTCHA vraci vysvetlitelnou chybu zdroje a scan pokracuje.
- Adaptery neobchazeji technicke ochrany.
- Aktualni parsery jsou best-effort; pri zmenach HTML je potreba upravit fixture a parser.
Vypocet ceny a jistoty
Implementace v backend/app/valuation.py:
- minimalne 3 porovnatelne nabidky
- median porovnatelnych cen
- konzervativni cena = median * faktor (default 0.85)
- ocekavany zisk = konzervativni cena - porizovaci naklady - poplatky
- marze = zisk / porizovaci naklady * 100
- status
Zajimavajen pri splneni limitu ceny, zisku, marze, poctu srovnani a dostatecne jistote
Rucne rizena AI pipeline
AI faze jsou oddelene od scanu a nikdy se nespousti automaticky:
POST /scanspouze bazarovy scan + deterministicky prefiltr + interni oceneniPOST /ai/normalizations/previewaPOST /ai/normalizationspouze rucne pro vybranelisting_idsPOST /ai/research/previewaPOST /ai/researchpouze rucne pro vybranelisting_ids
Automaticke retezeni je zakazane:
- scan -> normalizace
- normalizace -> research
- zmena ceny/popisu -> automaticky rerun
- otevreni seznamu/detailu -> automaticky AI call
Kazda nabidka ma oddelene stavy:
ai_normalization_statusai_research_status
Podporovane stavy: not_requested, queued, running, completed, failed, stale, skipped_budget, skipped_not_eligible.
AI API
POST /ai/normalizations/previewPOST /ai/normalizationsGET /ai/normalizations/{job_id}POST /ai/research/previewPOST /ai/researchGET /ai/research/{job_id}GET /ai/jobsPOST /listings/{id}/mark-ai-stale
Preview endpointy nikdy nevolaji placene AI. Spousteci endpointy vyzaduji explicitni seznam listing_ids a CSRF token.
Spusteni testu
Backend:
APP_PORT=3017 docker compose exec backend pytest
Frontend unit testy:
APP_PORT=3017 docker compose exec frontend npm run test
Frontend e2e smoke:
APP_PORT=3017 docker compose exec frontend npm run test:e2e
Troubleshooting
- Port conflict: nastav jiny
APP_PORT(napr.3017) - 401 po loginu: over
SESSION_SECURE_COOKIESvs. HTTP/HTTPS rezim - Migrace nesedi: spust
alembic upgrade headv backend kontejneru - SMTP fail: over reachable host/port z kontejneru a STARTTLS nastaveni
- Adapter chyby: zkontroluj HTML fixture a parser selektory