|
Some checks are pending
CI / test (push) Waiting to run
Covers all 8 services, image/Dockerfile, PHP config, FPM pool tuning, volume layout, network topology, startup order, local dev override, operational commands, and Gitea Actions CI. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> |
||
|---|---|---|
| .gitea/workflows | ||
| bin | ||
| config | ||
| docker | ||
| docs | ||
| migrations | ||
| public | ||
| src | ||
| templates | ||
| tests | ||
| translations | ||
| .editorconfig | ||
| .env | ||
| .env.dev | ||
| .env.test | ||
| .gitignore | ||
| .php-cs-fixer.dist.php | ||
| .php-cs-fixer.php | ||
| CLAUDE.md | ||
| composer.json | ||
| composer.lock | ||
| docker-compose.override.yml | ||
| docker-compose.yml | ||
| phpstan.neon | ||
| phpunit.dist.xml | ||
| phpunit.xml.dist | ||
| README.md | ||
| symfony.lock | ||
SuperSeller3000
Admin middleware for managing and selling refurbished IT hardware. Handles article ingestion via AI pipeline (photo → vision → specs → eBay texts), multi-channel publishing (eBay), and order processing with Frappe ERP invoicing.
Live: https://ss3k.schaunwama.de/admin
Architecture reference: docs/architecture.md
Full design doc: docs/superpowers/specs/2026-05-13-superseller3000-design.md
Quick Start
cp .env .env.local # fill in secrets — see .env for all required vars
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
docker compose exec app php bin/console app:api-keys: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 7 Streams |
| AI | Mistral Cloud API — Vision: pixtral-12b-2409, Text: mistral-large-latest |
| Web Search | Tavily API |
| Channel | eBay Inventory / Account / Fulfillment / Taxonomy APIs |
| ERP | Frappe ERPNext (sales invoices, customer sync) |
| Admin | EasyAdmin 5 |
| Auth | Symfony Security + TOTP 2FA · API keys via X-Api-Key header |
| Proxy | Caddy 2 (Auto-HTTPS) |
Running Tests
# Unit tests (fast, no external deps)
docker compose exec app php vendor/bin/phpunit tests/Unit/
# Single test file or method
docker compose exec app php vendor/bin/phpunit tests/Unit/Domain/Article/ArticleTest.php
docker compose exec app php vendor/bin/phpunit --filter testSomeMethod
# Integration tests (requires credentials in .env.local)
bin/test-integration
bin/test-integration tests/Integration/Infrastructure/Channel/Ebay/
# Static analysis (level 9, must be clean)
docker compose exec app php vendor/bin/phpstan analyse
# Code style
docker compose exec app php vendor/bin/php-cs-fixer fix --dry-run --diff
docker compose exec app php vendor/bin/php-cs-fixer fix
Admin Panel Features
- Articles — list with row click → detail, inline actions (activate, re-run AI, manage photos)
- Photo Management — per-article page: upload, delete, set main, drag-to-reorder
- AI Pipeline — per-job step tracking; re-run AI from article detail; failed jobs show real error
- Article Types — configurable attribute schemas (name, type, unit, options, required flag)
- eBay — category + business policy configuration per article type (fulfillment, payment, return, location pulled live from eBay account)
- eBay Aspect Import — typeahead category search, imports taxonomy aspects as attribute mappings
- Orders / Customers / Invoices — full read/manage view
- Prompt Templates — DB-backed, editable in admin,
{{variable}}substitution - Users — permission checkboxes per user; API keys via console
Article Ingest
Via Admin UI
Admin → Artikel einlesen — select article type, condition, stock quantity, take/upload photo. Pipeline starts automatically.
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"
# Poll status
curl https://ss3k.schaunwama.de/api/pipeline/jobs/<jobId> \
-H "X-Api-Key: <key>"
Pipeline A (photo): Vision → DB model cache check → (hit: copy texts, done) / (miss: Tavily search → JSON coding → Validation → Draft → eBay text)
Pipeline B (PXE dump): JSON coding → Validation → Draft → eBay text
After pipeline: admin reviews draft, sets price, activates → eBay listing published automatically (with photos).
eBay Setup
For each article type, configure in Admin → eBay → Kategorie-Konfigurationen:
- Assign article type and eBay category ID
- Select business policies (fulfillment, payment, return) — loaded live from your eBay account
- Select merchant location
Import aspect mappings via Admin → Artikeltypen → aspect import action.
Set the public URL for photo hosting in .env.local:
APP_PUBLIC_URL=https://ss3k.schaunwama.de
Architecture
Hexagonal (Domain / Application / Infrastructure). See docs/architecture.md for the full reference including all flows, entity relationships, queue details, and gotchas.
src/
Domain/ # Pure PHP — Article, ArticleType, Order, Customer, AIPipelineJob …
Application/ # Use cases, port interfaces (ChannelAdapterInterface, ErpAdapterInterface …)
Infrastructure/
AI/ # MistralClient, 4 AI agents (Vision, SpecsResearch, JsonCoding, EbayText)
Channel/ # EbayAdapter + 5 API clients, FrappeErpAdapter
Persistence/ # Doctrine repositories (PostgreSQL)
Messenger/ # Message classes + handlers (3 transports: ai_pipeline, orders, channel_sync)
Http/ # Symfony controllers, EasyAdmin CRUD, webhooks, public photo endpoint
| Transport | Retries | Used for |
|---|---|---|
ai_pipeline |
3 × 2 s | All AI pipeline steps |
orders |
5 × 1 s | Order processing, invoicing |
channel_sync |
5 × 2 s ≤ 60 s | Publish, stock sync, deactivate, tracking |
failed |
— | Dead-letter; replay via messenger:failed:retry |