2026-05-18 07:53:52 +00:00
|
|
|
menu.dashboard: Dashboard
|
|
|
|
|
menu.ingest_article: 'Artikel einlesen'
|
|
|
|
|
menu.articles: Artikel
|
|
|
|
|
menu.article_types: Artikeltypen
|
|
|
|
|
menu.attributes: Attribute
|
|
|
|
|
menu.section_pipeline: Pipeline
|
|
|
|
|
menu.active_jobs: 'Aktive Jobs'
|
|
|
|
|
menu.archive: Archiv
|
|
|
|
|
menu.ai_prompts: 'KI-Prompts'
|
|
|
|
|
menu.translations: Übersetzungen
|
|
|
|
|
menu.users: Benutzer
|
|
|
|
|
menu.logs: Logs
|
2026-05-19 07:13:51 +00:00
|
|
|
menu.section_ebay: eBay
|
|
|
|
|
menu.ebay_platform_configs: 'Kategorie-Konfigurationen'
|
2026-05-18 07:53:52 +00:00
|
|
|
menu.section_sales: Verkauf
|
|
|
|
|
menu.orders: Bestellungen
|
|
|
|
|
menu.customers: Kunden
|
|
|
|
|
menu.invoices: Rechnungen
|
|
|
|
|
menu.change_password: 'Passwort ändern'
|
|
|
|
|
menu.language_en: English
|
|
|
|
|
menu.language_de: Deutsch
|
|
|
|
|
crud.article.singular: Artikel
|
|
|
|
|
crud.article.plural: Artikel
|
|
|
|
|
crud.article_type.singular: Artikeltyp
|
|
|
|
|
crud.article_type.plural: Artikeltypen
|
|
|
|
|
crud.attribute.singular: Attribut
|
|
|
|
|
crud.attribute.plural: Attribute
|
|
|
|
|
crud.attribute_assignment.singular: Attributzuweisung
|
|
|
|
|
crud.attribute_assignment.plural: Attributzuweisungen
|
|
|
|
|
crud.customer.singular: Kunde
|
|
|
|
|
crud.customer.plural: Kunden
|
|
|
|
|
crud.order.singular: Bestellung
|
|
|
|
|
crud.order.plural: Bestellungen
|
|
|
|
|
crud.invoice.singular: Rechnung
|
|
|
|
|
crud.invoice.plural: Rechnungen
|
|
|
|
|
crud.log_entry.singular: 'Log-Eintrag'
|
|
|
|
|
crud.log_entry.plural: 'Log-Einträge'
|
|
|
|
|
crud.user.singular: Benutzer
|
|
|
|
|
crud.user.plural: Benutzer
|
|
|
|
|
crud.pipeline_job.singular: 'Pipeline-Job'
|
|
|
|
|
crud.pipeline_job.plural_active: 'KI-Pipeline — Aktiv'
|
|
|
|
|
crud.pipeline_job.plural_archive: 'KI-Pipeline — Archiv'
|
|
|
|
|
crud.prompt_template.singular: 'Prompt-Vorlage'
|
|
|
|
|
crud.prompt_template.plural: 'Prompt-Vorlagen'
|
|
|
|
|
crud.translation.singular: Übersetzung
|
|
|
|
|
crud.translation.plural: Übersetzungen
|
|
|
|
|
field.id: ID
|
|
|
|
|
field.name: Name
|
|
|
|
|
field.type: Typ
|
|
|
|
|
field.unit: Einheit
|
|
|
|
|
field.options: 'Optionen (eine pro Zeile)'
|
|
|
|
|
field.options_help: 'Nur relevant für Typ select / multi_select.'
|
|
|
|
|
field.required_attributes: Pflichtattribute
|
|
|
|
|
field.optional_attributes: 'Optionale Attribute'
|
|
|
|
|
field.inventory_number: 'Inventarnr.'
|
|
|
|
|
field.status: Status
|
|
|
|
|
field.step: Schritt
|
|
|
|
|
field.attempts: Versuche
|
|
|
|
|
field.started: Gestartet
|
|
|
|
|
field.error: Fehler
|
|
|
|
|
field.ai_results: 'KI-Ergebnisse'
|
feat: Frappe ERP matching, pipeline model cache, ACL, stock field, specs by type
Frappe ERP:
- findExistingCustomer() on FrappeErpAdapter — two-step name+address lookup
- FrappeHttpClient: add put() method; switch invoice submit to PUT docstatus=1 (Frappe v16)
- buildItemDescription() uses specsText + inventory number + serial number
- Integration tests: find Simon Kühn, create real 1337€ invoice, cancel+delete in tearDown
- FRAPPE_GENERIC_ITEM_CODE=SKU002 added to .env.local and bin/test-integration
Pipeline — model cache:
- PhotoUploadHandler: after vision, check DB for existing article with same modelNumber
- On match: copy ebayTitle/ebayDescription/specsText/attributes, skip specs+JSON+eBay steps
- DraftArticleHandler: apply model_match data and mark job complete directly
- ArticleRepository: findCompletedByModelNumber() query
Pipeline — specs by article type:
- SpecsResearchAgent: accept attributeFields list, format as bullet list in {{fields}} var
- SpecsResearchHandler: derive attribute names from ArticleType, pass to agent
- SpecsResearchMessage: add attributeFields param
- Prompt migration: replace hardcoded laptop spec list with {{fields}} placeholder
Article:
- specsText field (nullable text column + migration)
- stock field visible on index and editable in CRUD form
- addAttributeValue()/removeAttributeValue() adder-remover pair for Symfony form binding
- AttributeValue::getArticle() getter
- AttributeValueFormType: detect required attributes from ArticleType assignments, set required=true
- ManualIngestType: add stock/quantity field (default 1, min 1)
Users / ACL:
- PermissionVoter: define named permission constants + allPermissions()
- User: getGrantedPermissions()/setGrantedPermissions() helpers
- UserCrudController: permissions checkbox group on edit form
UI / assets:
- public/css/admin/custom.css: red asterisk for required fields
- DashboardController: register custom CSS
Infra:
- PipelineJobFailureListener: mark job failed (with real error) when Messenger exhausts retries
- doctrine.yaml: exclude app.inventory_seq from schema diff
- ErpAdapterInterface: add findExistingCustomer()
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-18 16:42:15 +00:00
|
|
|
field.stock: Anzahl
|
2026-05-18 07:53:52 +00:00
|
|
|
field.price: Preis
|
|
|
|
|
field.condition: Zustand
|
|
|
|
|
field.manufacturer: Hersteller
|
|
|
|
|
field.model_number: 'Modellnr.'
|
2026-05-18 10:06:36 +00:00
|
|
|
field.model_name: 'Modellname'
|
2026-05-18 07:53:52 +00:00
|
|
|
field.serial_number: 'Seriennr.'
|
|
|
|
|
field.condition_notes: Zustandshinweise
|
|
|
|
|
field.description: Beschreibung
|
|
|
|
|
field.ebay_description: 'eBay-Beschreibung'
|
|
|
|
|
field.attributes: Attribute
|
|
|
|
|
field.prompt_key: Schlüssel
|
|
|
|
|
field.prompt_key_help: 'Eindeutiger Bezeichner für den Prompt (z. B. <code>specs_research</code>).'
|
|
|
|
|
field.prompt_body: 'Prompt-Text'
|
|
|
|
|
field.prompt_body_preview: Vorschau
|
|
|
|
|
field.last_updated: 'Zuletzt geändert'
|
2026-05-18 09:10:59 +00:00
|
|
|
field.photos: Fotos
|
2026-05-18 07:53:52 +00:00
|
|
|
field.locale: Sprache
|
|
|
|
|
field.domain: Bereich
|
|
|
|
|
field.translation_key: Schlüssel
|
|
|
|
|
field.translation_value: Übersetzung
|
2026-05-18 11:02:46 +00:00
|
|
|
action.delete_attribute_confirm: 'Attribut löschen? Alle gespeicherten Werte in bestehenden Artikeln werden ebenfalls gelöscht.'
|
2026-05-18 07:53:52 +00:00
|
|
|
action.retry: Wiederholen
|
|
|
|
|
action.retry_confirm: 'Diesen Pipeline-Job ab dem aktuellen Schritt neu einreihen?'
|
|
|
|
|
action.rerun_ai: 'KI neu starten'
|
|
|
|
|
action.rerun_ai_confirm: 'Die gesamte KI-Pipeline für diesen Artikel neu starten? Attribute und eBay-Texte werden überschrieben.'
|
|
|
|
|
action.mark_as_draft: 'Als Entwurf markieren'
|
|
|
|
|
action.activate: Aktivieren
|
|
|
|
|
flash.pipeline_job_not_found: 'Kein ursprünglicher Pipeline-Job gefunden — Foto kann nicht ermittelt werden.'
|
|
|
|
|
flash.photo_not_found: 'Gespeichertes Foto nicht gefunden unter: %path%'
|
|
|
|
|
flash.pipeline_requeued: 'KI-Pipeline für %label% neu gestartet — Attribute und eBay-Texte werden aktualisiert.'
|
|
|
|
|
flash.article_marked_draft: 'Artikel als Entwurf markiert.'
|
|
|
|
|
flash.article_missing_attributes: 'Aktivierung nicht möglich: fehlende Attribute: %attrs%'
|
|
|
|
|
flash.article_activated: 'Artikel aktiviert und zur Kanalveröffentlichung eingereicht.'
|
|
|
|
|
flash.job_requeued: 'Job %id% ab Schritt %step% neu eingereiht.'
|
|
|
|
|
pipeline.step.vision: 'Foto analysiert'
|
|
|
|
|
pipeline.step.specs_research: 'Specs recherchiert'
|
|
|
|
|
pipeline.step.json_coding: 'Attribute kodiert'
|
|
|
|
|
pipeline.step.draft_article: 'Artikel erstellt'
|
|
|
|
|
pipeline.step.ebay_text: 'eBay-Texte generiert'
|
|
|
|
|
pipeline.step.validation: Validierung
|
|
|
|
|
pipeline.event.queued: 'Job #%inv% zur Pipeline hinzugefügt'
|
|
|
|
|
pipeline.event.processing_start: 'Job #%inv% gestartet'
|
|
|
|
|
pipeline.event.processing_step: 'Job #%inv%: %step%'
|
|
|
|
|
pipeline.event.completed: 'Job #%inv% abgeschlossen ✓'
|
|
|
|
|
pipeline.event.failed: 'Job #%inv% fehlgeschlagen: %reason%'
|
|
|
|
|
pipeline.event.needs_review: 'Job #%inv% benötigt manuelle Prüfung'
|