No description
Find a file
Simon Kuehn 0fdb4979c1 fix: route EbayAspectImportController redirects through AdminUrlGenerator
Plain redirectToRoute() bypasses EasyAdmin's AdminRouterSubscriber, so
the admin context (ea.i18n etc.) was never set and the EasyAdmin layout
threw "Impossible to access i18n on null". Using AdminUrlGenerator wraps
the redirect URL in the EasyAdmin routing layer, keeping context alive.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 20:15:31 +00:00
.gitea/workflows feat: add Gitea Actions CI (CS Fixer, PHPStan, Pest + migrations) 2026-05-14 04:25:50 +00:00
bin feat: eBay sandbox integration — env config + taxonomy/adapter tests 2026-05-18 18:02:49 +00:00
config feat: Frappe ERP matching, pipeline model cache, ACL, stock field, specs by type 2026-05-18 16:42:15 +00:00
docker feat: add erpstaging.schaunwama.de reverse proxy to frappe docker 2026-05-18 11:39:14 +00:00
docs/superpowers docs: add README and update design doc for post-plan features 2026-05-18 17:41:33 +00:00
migrations feat: eBay aspect import — match/create attributes from eBay taxonomy 2026-05-18 18:30:45 +00:00
public feat: Frappe ERP matching, pipeline model cache, ACL, stock field, specs by type 2026-05-18 16:42:15 +00:00
src fix: route EbayAspectImportController redirects through AdminUrlGenerator 2026-05-18 20:15:31 +00:00
templates fix: replace unknown Twig toString filter with toRfc4122() call 2026-05-18 20:12:17 +00:00
tests feat: expose eBay aspect usage tier (RECOMMENDED vs OPTIONAL) 2026-05-18 18:21:31 +00:00
translations feat: Frappe ERP matching, pipeline model cache, ACL, stock field, specs by type 2026-05-18 16:42:15 +00:00
.editorconfig chore: add tooling config, test bootstrap, env templates and docs 2026-05-17 22:44:16 +00:00
.env feat: replace Mistral web_search with Tavily for specs research 2026-05-18 08:35:52 +00:00
.env.dev chore: add tooling config, test bootstrap, env templates and docs 2026-05-17 22:44:16 +00:00
.env.test feat: eBay sandbox integration — env config + taxonomy/adapter tests 2026-05-18 18:02:49 +00:00
.gitignore feat: add PHPStan level 9, PHP CS Fixer, Pest; fix docker user=1000 to avoid root-owned files 2026-05-14 04:25:30 +00:00
.php-cs-fixer.dist.php chore: add tooling config, test bootstrap, env templates and docs 2026-05-17 22:44:16 +00:00
.php-cs-fixer.php feat: implement Plan 2 — Article Management API 2026-05-14 05:19:20 +00:00
composer.json feat: admin panel, Mistral client, attribute management, API key command 2026-05-17 20:15:13 +00:00
composer.lock feat: admin panel, Mistral client, attribute management, API key command 2026-05-17 20:15:13 +00:00
docker-compose.override.yml feat: add Docker Compose environment with Caddy, PostgreSQL 17, Redis, PHP-FPM workers 2026-05-14 04:14:55 +00:00
docker-compose.yml fix: raise PHP-FPM pool to 30 workers to prevent SSE starvation 2026-05-18 09:02:34 +00:00
phpstan.neon feat: implement Plan 2 — Article Management API 2026-05-14 05:19:20 +00:00
phpunit.dist.xml chore: add tooling config, test bootstrap, env templates and docs 2026-05-17 22:44:16 +00:00
phpunit.xml.dist feat: add PHPStan level 9, PHP CS Fixer, Pest; fix docker user=1000 to avoid root-owned files 2026-05-14 04:25:30 +00:00
README.md docs: add README and update design doc for post-plan features 2026-05-18 17:41:33 +00:00
symfony.lock feat: admin panel, Mistral client, attribute management, API key command 2026-05-17 20:15:13 +00:00

SuperSeller3000

Admin middleware for managing and selling refurbished IT hardware. Handles article ingestion via AI pipeline (photo → vision → specs → eBay text), multi-channel publishing (eBay), and order processing with Frappe ERP invoicing.

Live: https://ss3k.schaunwama.de/admin
Full design doc: docs/superpowers/specs/2026-05-13-superseller3000-design.md


Quick Start

cp .env .env.local          # fill in secrets (DB, Redis, AI keys, eBay, Frappe)
docker compose up -d
docker compose exec app php bin/console doctrine:migrations:migrate --env=prod
docker compose exec app php bin/console app:users:create --env=prod

Workers start automatically via Docker Compose (worker-ai, worker-orders, worker-channel).


Tech Stack

Layer Technology
Language / Framework PHP 8.4 · Symfony 8.4
ORM Doctrine ORM
Database PostgreSQL 17 — schemas: app, logs, logs_archive
Queue Symfony Messenger + Redis Streams
AI Ollama (local, SSH-tunnel) or Mistral Cloud API — alias-switchable in services.yaml
Web Search Tavily API (TAVILY_API_KEY)
Admin EasyAdmin 5
Auth Symfony Security + TOTP 2FA (scheb/2fa-totp)
Proxy Caddy 2 (Auto-HTTPS)

Running Tests

# Unit tests (fast, no external deps)
docker compose exec app php vendor/bin/phpunit tests/Unit/ --testdox

# Integration tests (requires staging credentials in .env.local)
bin/test-integration

# Single integration file
bin/test-integration tests/Integration/path/to/Test.php

# Static analysis + code style
docker compose exec app composer phpstan
docker compose exec app composer cs-check

AI Backend

Switch between Ollama and Mistral in config/services.yaml:

# Ollama (default — local via SSH tunnel)
App\Infrastructure\AI\OllamaClientInterface:
    alias: App\Infrastructure\AI\OllamaClient

# Mistral Cloud
App\Infrastructure\AI\OllamaClientInterface:
    alias: App\Infrastructure\AI\MistralClient

Set models via env vars: AI_TEXT_MODEL, AI_VISION_MODEL. After switching: docker compose exec app php bin/console cache:clear.


Admin Panel Features

  • Articles — list (click row → detail view, Edit as action), ingest form with stock quantity, attribute validation with required-field highlighting
  • AI Pipeline — per-job progress view with step tracking; failed jobs show the real error; re-run AI from article detail
  • Article Types — configurable attribute schemas (name, type, unit, options, required flag); attributes drive specs-research field list
  • Users — permission checkboxes per user (ARTICLES_MANAGE, PIPELINE_RUN, ORDERS_MANAGE, etc.)
  • Orders / Customers / Invoices — full read/manage view
  • Prompt Templates — editable via admin (DB-backed, {{variable}} substitution)

Manual Article Ingest

Admin → New Article (or via API):

curl -X POST https://ss3k.schaunwama.de/api/pipeline/photo-upload \
  -H "X-Api-Key: <key>" \
  -F "articleTypeId=<uuid>" \
  -F "condition=good" \
  -F "stock=1" \
  -F "photo=@/path/to/photo.jpg"

Pipeline: Photo → OllamaVision (model number) → DB model cache check(cache hit: copy + done) / (cache miss: Tavily search → JsonCoding → Validation → Draft → eBay text)


API Keys

Generated via console only (raw key shown once):

docker compose exec app php bin/console app:api-keys:create --env=prod

Use as X-Api-Key: <rawKey> header.


Architecture

Hexagonal (Domain / Application / Infrastructure). See design doc for full details.

src/
  Domain/          # Pure PHP — Article, ArticleType, Order, Customer, AIPipelineJob …
  Application/     # Use cases, orchestration via interfaces
  Infrastructure/
    AI/            # OllamaClient, MistralClient, 4 AI agents
    Channel/       # EbayAdapter, FrappeErpAdapter
    Search/        # TavilyWebSearch
    Persistence/   # Doctrine repositories (PostgreSQL)
    Messenger/     # Message classes + handlers (3 queues: ai_pipeline, orders, channel_sync)
    Http/          # Symfony controllers, EasyAdmin CRUD, webhooks

All plans (16) complete. Active development tracked via Claude Code sessions.