Klärungspunkte beantwortet (26.08.): Varianten haben eigene Artikelnummer
(Connector sendet künftig Variations-Nr.); Gramm-Rechnung über ml+Dichte auf
Rohstoff- UND Produktebene (Produkt-Füllgewicht, Rohstoff-Dichte); getrennte
pflegbare Buchungsgründe Ein/Aus; Waldbröl auf Köln übernehmen, Funktion bleibt.
Nur D-3 (Shop-Status-Cron) noch kundenseitig in Prüfung. AP-34/35/42/48/50
entsprechend geschärft.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Kundenfeedback aus der Testphase am Code + Live-DB verifiziert und in einen
Umsetzungsplan überführt (AP-34…AP-51, ~15–26 PT): 9 bestätigte Bugs (u. a.
Varianten-Artikelnummer, Produktionsmengen 100 g statt Füllmenge, leere
Rezepturphasen, „Enthalten in"-Doppelung) plus Erweiterungen. WooCommerce-Ampel
ist voraussichtlich shopseitig (Status-Cron/Auth), kein ERP-Fehler. Sechs
Klärungspunkte (D-1…D-6) offen. Noch nichts umgesetzt.
Rohfeedback des Kunden liegt als entwicklungsplan-aktualisiert-2026-08-26.md bei.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Product-Management-Ordner in 00-konzept / 01-entwicklungsplaene / 02-audit /
03-status-und-vorschlaege gegliedert (Datei-Moves bereits in 037ec4d). Ergänzt:
- README.md als Einstieg mit grober Roadmap (Ist-Stand live/in Test, erledigte
APs, offene AP-32/33c/14/15/16/17, Deckel-Varianten-Vorschlag) und Verweisen.
- Leistungsübersicht + Deckel-Varianten-Vorschlag (23.07.) in den Ordner
einsortiert und nun mitversioniert.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Bots klopfen /oauth/authorize ohne gültige OAuth-Parameter ab; Passport
wirft dann korrekt einen 4xx-Fehler. Da der Handler bei jeder gemeldeten
Exception mailt und die API ausschliesslich Personal Access Tokens nutzt
(Authorize-Flow nie legitim genutzt), war jede dieser Mails Rauschen.
OAuthServerException wandert in $dontReport – Endpoint-Verhalten bleibt
unveraendert, nur der Mail-Versand fuer diese Client-Fehler entfaellt.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
usersDetail/customersDetail (samt users/usersStore/customersStore) waren
in einem großen Kommentarblock auskommentiert — die darin ergänzten
AP-33-shipped_status_locked-Guards also wirkungslos; der aktive Guard
sitzt in detail(). Block und die bereits auskommentierten Routen
ersatzlos entfernt.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Indizes auf shopping_orders.shipped/shipped_at/created_at (Board-Filter,
Tages-Kacheln) und products.wp_number (SKU-Auflösung). Die
API-Bestellungen-Seite lud das komplette JSON-payload für alle 500 Zeilen
und serialisierte es in Inline-Attribute; jetzt persistierte
positions_count, Liste ohne payload, Inhalt on-demand über show-Endpoint.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Der Default-Scope 'recipe' blendet rezepturlose Rohstoffe aus, das
Sidebar-Badge zählt aber alle aktiven kritischen — Badge und Seite
konnten sich widersprechen. Die recipe-Ansicht zeigt jetzt einen Hinweis
mit 'Alle anzeigen', sobald das Badge mehr zählt; Empty-State-Text
scope-abhängig.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Bestellnummern-Links auf admin_sales_detail (admin >= 7) waren für
Versand-Mitarbeiter tote Links (stiller Redirect) — jetzt rollenabhängig.
Kachel-Zähler und pick/ready-Filter rechnen über alle offenen
Bestellungen statt über die neuesten 500; gekappt wird nur die Anzeige,
der Hinweis-Banner zeigt 'neueste n von total' korrekt. whereDate durch
indexfähiges whereBetween ersetzt; Packlisten-Toggle über data-order-id;
Gewicht über formatNumber().
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
document('combined') lief bei fehlender Alt-PDF ungeprüft in eine
PDFMerger-Exception (500); der Sammel-Druck prüfte nur den Lieferschein,
eine fehlende Rechnungs-PDF ließ den ganzen Batch platzen. Neue zentrale
InvoiceRepository::ensureFilesOnDisk() ersetzt den dreifach kopierten
Altdaten-Check (MailLogistic 2x, batchDocuments); Merge-/Response-Code im
OrderFulfillmentController zu mergedPdf()/pdfResponse() dedupliziert.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
recordTransfer() löste die SKU erneut auf und markierte nur unbekannte
Artikel als Fehler — Zeilen mit gültiger SKU aber fehlender Menge/Preis
wurden verworfen und trotzdem grün protokolliert. prepareOrder() reicht
jetzt included/product_id/product_name durch; failed = Position nicht
übernommen. Entfernt zugleich die N+1-Produkt-Queries je Position.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Die Brücke hätte live nicht funktioniert: Connector 1.4.0 sendete die
label_url aus dem per 'deny from all' geschützten DHL-Ordner (403), dazu
SSRF-Risiko durch serverseitigen Abruf einer Client-URL und Timeout-
Mismatch (20 s Download vs. 5 s WordPress-Default). Der Connector liest
die PDF jetzt vom Shop-Dateisystem (realpath-Pinning auf wp-uploads) und
sendet sie Base64; storeWpLabel() validiert und speichert ohne Http::get;
tote Shop-Link-Fallbacks aus den Views entfernt; Connector-Timeout 30 s.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Der Auto-Storno der Zahlungserinnerung schrieb shipped=10 direkt und rief
nur syncSaleStock() — Margen-Storno-Flag, pending_to/shipped_at-Reset und
Promotions-/Guthaben-Folgen fehlten. Die Partnerprovision einer
versendeten, nie bezahlten Bestellung wäre zahlbar geblieben.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Der Schutz historischer Bestellungen hing an shipped_at, das der
OrderStatusService beim Status-Toggle nullt und neu stempelt — Storno +
erneutes Versenden einer Alt-Bestellung hätte rückwirkend vom heutigen
Bestand abgezogen. Migration mit einmaligem Backfill (shipped_at vor
16.07.2026), Guard prüft nur noch das Flag.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
compose_label_data() liest das Meta-Feld _pr_shipment_dhl_label_tracking
(DHL for WooCommerce); write_order_items() schickt Label-URL + Sendungsnummer
beim wp/order-Transfer mit. Neuer Listener auf pr_save_dhl_label_tracking
reicht Labels nach, die erst nach der Übertragung erstellt werden (nur bei
bereits übertragenen Bestellungen, via neuem wp/label-Endpoint).
Connector-Doku auf die konkrete Umsetzung aktualisiert.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Bestell-Übertragung (wp/order) akzeptiert wp_label_url + wp_tracking_number:
Label-PDF wird als lokale Kopie im privaten Storage gespeichert (Shop-URL ist
öffentlich erratbar; Kopie überlebt Löschung im Shop), Sendungsnummer landet
in shopping_orders.tracking. Neuer Endpoint wp/label zum Nachreichen
(Connector-Hook pr_save_dhl_label_tracking), wp/status liefert die
Sendungsnummer an den Shop zurück. Abwicklungs-Board + Bestell-Details zeigen
Label-Download (copyreader-Dokumentroute type=label, Fallback Shop-Link) und
Sendungsnummer. Download-Fehler blockieren die Übertragung nie.
Doku: Connector-Update-Anleitung (dev/product management), Hinweise,
Testleitfaden §11, Plan-Protokoll. pint.json schließt dev/ (Fremdcode) aus.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Nachtrag zum Lieferschein-Fix (7d77314): Fehlte die Rechnungs-PDF auf der
Platte (Altdaten), brach MailLogistic::build() still ab — die Mail ging ohne
Anhänge bzw. gar nicht raus, obwohl das UI Erfolg meldete. Jetzt wird die
Rechnung wie der Lieferschein mit bestehender Rechnungsnummer regeneriert.
Hinweise-Doku und Plan-Protokoll fortgeschrieben.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Inkl. dokumentationspflichtiger Regel (Kundenwunsch): WaWi-Status hat Vorrang,
Detailseiten überschreiben ihn nicht mehr automatisch.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Kundenanforderung 16.07.2026 als AP-33a/b/c in Plan §4 aufgenommen:
Abwicklungs-Board (Konfektionierung, Dokumente, Versand-Klick), Sammel-PDFs
(Lieferscheine/Rechnungen/Etiketten), Etiketten-Integration mit AP-32;
Klärungspunkte für den Kunden dokumentiert, Roadmap neu nummeriert.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Erneutes Speichern des Versandstatus einer Alt-Bestellung (shipped_at vor
16.07.2026) hätte rückwirkend vom heutigen Bestand abgezogen. syncSaleStock()
überspringt historische Bestellungen jetzt per Stichtag SALE_STOCK_SINCE.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Kundenanforderung 15.07.: Versand komplett im System inkl. Label-Erstellung
ueber die DHL Parcel DE Shipping API. Gleicher Andockpunkt wie AP-13
(Versand-Statuswechsel). AP-13-Ansatz vom Kunden bestaetigt.
Klaerungspunkte (DHL-Konto, Versandprodukte, CH-Zoll, Druck-Setup) notiert.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Plugin-Trigger verifiziert (Kundendaten automatisch, Warenkorb per
Fulfillment-Button, Status per Cron-Poll). Bestandsabzug wird reiner
Serverseiten-Hook am Versand-Statuswechsel, kein Plugin-Update noetig.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Der in den Partner-Shops installierte WooCommerce-Connector, der Bestellungen
per REST an /api/wp/* uebertraegt (Kunde anlegen, Warenkorb, Status-Abgleich).
Grundlage fuer AP-13 (Shop-Bestandsabzug beim Versand).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Chargen-Existenz-Check beim Buchen (JSON-Endpoint batch-check): Hinweis
„Charge bereits im Haus" + Vorbelegung MHD/Qualität aus dem letzten Eingang
- Rohstoffbestand-Detail: Chargen je batch_number summiert
(InventoryService::chargeGroupsForIngredient), Einkäufe als Unterzeilen
- Produktion: Charge-Dropdown je Charge mit Summen-Rest (batches im
Recipe-Payload), Verbrauch wird per expandBatchLines FEFO auf die
Einzel-Einkäufe der Charge verteilt; Service-API bleibt je stock_entry
- Jeder Einkauf bleibt eigener stock_entry (Preis/Datum/Audit)
- Hinweise-Doku + Plan V6.0 §6 fortgeschrieben
Tests: StockEntryChargeMergeTest (7 neu); Suite 193 grün, 698 Assertions
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- ingredients.exclude_from_stock (Checkbox im INCI-Formular, z. B. Allergene):
erscheint nie im Rohstoffbestand und nicht im Kritisch-Badge
- Rohstoffbestand-Uebersicht: Umschalter "Alle" / "Nur aus Herstellerrezepturen"
(?scope=recipe, nutzt scopeUsedInActiveRecipes aus AP-21)
- Fix: AP-21-Migrationen hatten identischen Timestamp (add_storage lief vor
create_storage und scheiterte auf MySQL am FK) - umbenannt auf 120753,
Teilreste bereinigt, Migrationen sauber ausgefuehrt
- Hinweise-Doku fortgeschrieben
Tests: RawMaterialStockTest +2 (volle Suite 172 gruen, 624 Assertions)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Abstrakte SettingCrudController-Basis für die kleinen Stammdaten-CRUDs
- TaxRate/DeliveryTime/DisposalReason/MaterialQuality/Location/SupplierCategory/PackagingMaterial auf ~25-Zeilen-Konfiguration reduziert
- Identische Update*Request-Klassen entfernt (Update nutzt Store-Request, via updateRequestClass() überschreibbar)
- Bilanz -441/+73 Zeilen; Grundlage für die Lagerort-CRUDs in AP-21
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>