Commit graph

157 commits

Author SHA1 Message Date
d51860af39 Warenwirtschaft: AP-45 + AP-47 — Verpackung aus Produktionsergebnis, Produktionsrelevant-Flag
AP-45: Verpackungsverbrauch (Etikett/Tiegel) wird jetzt aus dem tatsächlichen
Produktionsergebnis gebucht — je Ergebnisprodukt dessen eigene Stückliste ×
Ergebnismenge, über alle Outputs summiert — statt aus der geplanten Stückzahl.
syncPackagingSnapshot liest die production_outputs und läuft daher nach
persistOutputs (store + update umgestellt).

AP-47: Neues Produkt-Kennzeichen „produktionsrelevant" (Boolean, Default true).
Nur so markierte Produkte erscheinen in der Produktions-Auswahl
(ProductionController create/edit/copy) und in der „Enthalten in"-Box des
Rohstoffbestands (blendet z. B. Aloe-Handelsware und Zweitgrößen aus).
Checkbox im Produktformular (mit Hidden-Fallback 0). Migration Default true,
damit Bestandsdaten unverändert bleiben.

Migrationen add_production_relevant auf Dev-/Live-DB ausgeführt. 4 Tests, Suite 314 grün.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-28 08:38:59 +00:00
e6007efc41 Warenwirtschaft: AP-46 — INCI-Liste nach Einsatzkonzentration sortiert
Die INCI-Liste (Hersteller-Rezeptur) in der Produktionsmaske wird jetzt nach
Anteil % absteigend sortiert dargestellt (null-Anteile zuletzt). Reine
Anzeige-Sortierung einer Kopie — die Chargen-Zuordnung unten bleibt in
Phasen-/pos-Reihenfolge.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-28 08:38:59 +00:00
4c6a57b0f1 Warenwirtschaft: AP-40 + AP-41 — Bestand/Differenz-Spalten, Ablage, Verpackung oben, Phasen-Gramm
AP-40: INCI-Tabelle der Produktion um zwei Spalten ergänzt — „Bestand" (aktueller
Rohstoffbestand je INCI, global) und „Differenz" (Bestand − Soll; negativ rot =
Fehlmenge, sonst grün). Spaltenkopf „Regal" → „Ablage". Bestand kommt aus
InventoryService::remainingByIngredient und wird als current_stock in den
recipeJson-Payload gehängt (lazy aufgelöst — InventoryService hängt selbst von
ProductionService ab, Konstruktor-Injektion wäre zirkulär).

AP-41: „Verpackung (Vorschau)" direkt unter die INCI-Tabelle verschoben (man sieht
auf einen Blick den Gesamtbedarf). Je Phase die Gesamt-Gramm hinter dem Namen
(„Phase A (345 g)"), aktualisiert sich mit Stückzahl und Füllgewicht-Skala.

Test für den current_stock-Payload ergänzt. Suite 311 grün.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-28 08:27:43 +00:00
744b36cdcb Warenwirtschaft: AP-35 + AP-39 — Produktionsmengen auf Füllgewicht + ±5 % Abwiegen
AP-35 (Mengenberechnung): Die Hersteller-Rezeptur ist in Prozent hinterlegt; die
Sollmengen skalieren jetzt auf das Füllgewicht statt fest auf ~100 g. Neuer
Faktor recipeGramScale = Füllgewicht/100. Basis = neues, optionales Produkt-Feld
"fill_weight" (g); ist es leer, gilt bei ml-Produkten (unit=1) die Füllmenge
(contents_total) als Gramm (1 g/ml). Ohne Massenbasis (z. B. Stück-Produkte)
bleibt es beim Altverhalten (Anteil = Gramm), sodass Bestandsprodukte/Tests
unverändert rechnen. Skala wird an die Maske durchgereicht (recipe_gram_scale),
damit Client und Server identisch rechnen (Service + 4 JS-Stellen).

AP-39 (Abwiegen): Die Ist-Menge je INCI muss nicht mehr aufs Gramm passen —
assertLinesMatchRecipe erlaubt ±5 % (kleiner absoluter Sockel), gebucht wird der
reale Ist-Wert. Status-Ampel in der Maske: Orange = nichts eingetragen,
Grün = eingetragen und ±5 %, Rot = >5 % daneben (Zahlendreher-Schutz).

Migration add_fill_weight_to_products auf Dev-/Live-DB ausgeführt (nullable).
Product fillable/cast + Produktformular-Feld ergänzt. 5 Tests, Suite 310 grün.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-27 14:36:52 +00:00
d60947c34d Warenwirtschaft: AP-36 — Rezeptur-Textphasen ohne Rohstoffe anzeigen
Phasen ohne Rohstoffzeile (reine Hinweisphasen wie „Vorbereitung"/„Nachbereitung")
verschwanden in der Produktionsmaske, weil buildPhaseGroups() leere Gruppen
wegfilterte. Filter so angepasst, dass benannte Phasen erhalten bleiben und nur
der namenlose „lose" Sammeltopf verworfen wird. Die Phasen kommen serverseitig
bereits in pos-Reihenfolge (recipePhases orderBy pos), sodass „Vorbereitung"
korrekt über „Phase A" steht. Test sichert den recipeJson-Datenvertrag ab.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-27 13:59:51 +00:00
00be848604 Warenwirtschaft: AP-37 — Rohstoffbestand „Enthalten in" nicht mehr doppelt
Jedes Produkt trägt einen Rohstoff i. d. R. in zwei product_ingredients-Zeilen
(recipe_type manufacturer + product); die belongsToMany-Relation Ingredient::products
lieferte das Produkt dadurch doppelt in der „Enthalten in"-Box. In
RawMaterialStockController::show() die Produktliste nach ID dedupliziert
(setRelation), wovon auch der abgeleitete Produktbestand profitiert. Reine
Anzeige-Korrektur, Pivot-Daten unangetastet. Test ergänzt.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-27 13:56:56 +00:00
5c5078bf64 Warenwirtschaft: Plan V7.0 — Kundenentscheide D-1…D-6 eingearbeitet
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>
2026-08-27 12:07:54 +00:00
d93c676b6b Warenwirtschaft: Entwicklungsplan V7.0 (Testphasen-Feedback 26.08.)
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>
2026-08-26 11:03:28 +00:00
29ced440b0 Warenwirtschaft: Doku-Ordner sortiert + Gesamt-Roadmap (README)
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>
2026-08-26 10:38:04 +00:00
a13c0f2ed1 Warenwirtschaft: tote Backup-Route-Dateien entfernt
routes/api 2.php und routes/web_bak.php werden nicht geladen (Bootstrap lädt
routes/api.php + web.php) und stiften nur Verwirrung. route:list unverändert.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-26 10:37:44 +00:00
d82d244738 Warenwirtschaft: API-Bestellannahme gehärtet + Klartext-Credentials entfernt
Review 26.08.2026 (Testphase). Änderungen in ShoppingUserController::order():

- Bestellanlage läuft transaktional (DB::transaction um makeShoppingOrder) —
  schlägt das Anlegen der Positionen fehl, bleibt keine halbe Bestellung zurück.
- Bestätigungsmail hinter den Commit verschoben und fehlertolerant (try/catch,
  Log-Warnung): ein SMTP-Fehler lässt die bereits gespeicherte Übertragung nicht
  mehr auf HTTP 500 laufen. Vorher meldete der Shop dann Fehlschlag, und der
  Retry scheiterte an der „Bestellung existiert bereits"-Sperre → verwaiste
  Bestellung.
- Preis-Abgleich als Integer-Cent (int) round(price*100) statt Gleitkomma-!=,
  das sonst falsche „different price"-Meldungen erzeugte (19,99 * 100 = 1998.99…).
- Auskommentierte API-Zugangsdaten (Mail/Passwort) aus dem Quelltext entfernt —
  Passwort bitte rotieren, falls je real genutzt.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-26 10:37:43 +00:00
037ec4d34b Fix: OAuth-Client-Fehler lösen keine Exception-Mail mehr aus
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>
2026-08-26 10:25:17 +00:00
7265d9cd19 Warenwirtschaft: Test — API verarbeitet Produkte mit show_on=10 (intern)
Bestätigt, dass die Bestellannahme rein über die WP-Nummer zuordnet und
show_on nur die Anzeige steuert — Produkte „zur internen Berechnung"
sind damit API-bestellbar, ohne in Shops/Bestelllisten aufzutauchen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 09:42:51 +00:00
0e27478b44 Warenwirtschaft: API ordnet Variations-SKUs dem Basisprodukt zu
Shop-Variationen (z. B. „10042-1") sind dasselbe Produkt mit derselben
WP-Nummer. Bei der Bestellannahme zählt für die Zuordnung nur der Teil
vor dem ersten „-"; die Original-SKU bleibt im API-Protokoll erhalten.
Leere Basis (z. B. „-1") wird nicht zugeordnet statt auf 0 zu matchen.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 09:25:10 +00:00
c171aa269a Warenwirtschaft: WP-Nummer aus Artikelnummer ableiten, wenn leer
Beim Produkt-Speichern wird eine leere wp_number aus der Artikelnummer
(number) befüllt, reduziert auf reine Ziffern (Integer-Spalte). Die
Ableitung passiert vor der Validierung, damit die Unique-Regel greift.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 09:17:53 +00:00
8b0a598ba6 Warenwirtschaft: Bugfix — Produkt speichern warf MethodNotAllowed (DELETE)
Das Lösch-Formular für gespeicherte Rezeptur-Inhaltsstoffe war in das
Produkt-Formular verschachtelt; Browser verwerfen das innere <form>-Tag,
wodurch _method=DELETE ins Speichern-Formular leakte. Jetzt Button, der
per JS ein eigenes Formular außerhalb erzeugt und abschickt.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-21 08:45:48 +00:00
93d5afca13 Warenwirtschaft: Review-Fix — toten Code in SalesController entfernt
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>
2026-07-20 13:19:26 +00:00
50243a07b4 Warenwirtschaft: Review-Fix — Indizes + schlanke API-Bestellungen-Seite
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>
2026-07-20 13:02:47 +00:00
f4256bfc89 Warenwirtschaft: Review-Fix — Hinweis auf kritische Rohstoffe außerhalb der Rezepturen
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>
2026-07-20 12:43:20 +00:00
80d0687f95 Warenwirtschaft: Review-Fix — Abwicklungs-Board (Copyreader-Links, 500er-Cap, Details)
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>
2026-07-20 12:40:03 +00:00
f28f4b4b68 Warenwirtschaft: Review-Fix — Altdaten-PDFs zentral regenerieren (ensureFilesOnDisk)
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>
2026-07-20 12:28:41 +00:00
8ad0f65947 Warenwirtschaft: Review-Fix — API-Protokoll markiert verworfene Positionen korrekt
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>
2026-07-20 10:29:37 +00:00
1b9b6adc44 Warenwirtschaft: Review-Fix — AP-32-Label als Base64 übertragen (Connector 1.5.0)
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>
2026-07-20 10:06:39 +00:00
ddd6dde593 Warenwirtschaft: Review-Fix — Mahnwesen-Storno über OrderStatusService::setShipped
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>
2026-07-20 09:47:20 +00:00
3eb14762e7 Warenwirtschaft: Review-Fix — Stichtags-Schutz als unveränderliches Flag (sale_stock_exempt)
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>
2026-07-20 09:41:01 +00:00
e6af987237 Warenwirtschaft: Rohstoffbestand — Default „Nur aus Herstellerrezepturen" (Kundenentscheid 17.07.2026)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 12:07:54 +00:00
4f9dca88de Connector-Plugin 1.4.0: DHL-Label an das Partnercenter übertragen
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>
2026-07-17 11:42:30 +00:00
0eed974576 Warenwirtschaft: AP-32-Brückenlösung — DHL-Label aus WooCommerce übernehmen
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>
2026-07-17 11:35:40 +00:00
a1f94ea427 Warenwirtschaft: Logistik-Mail regeneriert auch fehlende Rechnungs-PDF
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>
2026-07-16 13:19:12 +00:00
6051aa6ea1 Warenwirtschaft: Doku — Lieferschein-Fix in Hinweisen und Plan-Protokoll
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 12:12:23 +00:00
7d77314805 Warenwirtschaft: Bugfix — Logistik-Mail hängt den Lieferschein IMMER an
Kundenmeldung 16.07.2026: Fehlversand an die Rechnungsadresse, weil der
Lieferschein (mit der Lieferadresse) in der Versand-Mail fehlte. Ursache:
MailLogistic hängte ihn nur bei White-Label-Bestellungen an. Jetzt wird der
Lieferschein unabhängig von Logo/White-Label immer mitgesendet; fehlt die
PDF-Datei auf der Platte (Altdaten), wird sie mit bestehender Rechnungsnummer
regeneriert. Dazu tote Duplikat-Klasse app/Mail/MailLogitic.php entfernt
(Tippfehler-Dateiname, definierte dieselbe Klasse in einer Altversion ganz
ohne Lieferschein-Anhang — Kollisionsrisiko im Classmap-Autoload).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 12:11:37 +00:00
748f259949 Warenwirtschaft: Doku — Blockabschluss AP-13/33a/33b, Testphase; AP-32/33c nachgelagert (Kundenentscheid 16.07.2026)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 12:05:19 +00:00
96615258e9 Warenwirtschaft: Doku — AP-33b abgeschlossen (Hinweise, Testleitfaden, Plan-Protokoll)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 12:01:19 +00:00
1252c30820 Warenwirtschaft: AP-33b Sammel-Dokumente — Lieferscheine/Rechnungen der Auswahl als ein PDF
Checkbox-Auswahl im Abwicklungs-Board (Alle-auswählen, Zähler in den Buttons)
+ zwei Sammel-Aktionen: „Lieferscheine drucken" und „+ Rechnungen" — je ein
zusammengeführtes PDF (PDFMerger/FPDI) im neuen Tab zum Stapeldruck. Fehlende
Dokumente werden dabei ohne Mailversand erzeugt, auf der Platte fehlende
Altdateien mit bestehender Nummer regeneriert. API-Bestellungen sind von der
Auswahl ausgenommen (deaktivierte Checkbox, Rechnung liegt im externen Shop)
und werden in gemischter Auswahl übersprungen; max. 100 je Druck.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 12:00:10 +00:00
c21cc63428 Warenwirtschaft: AP-33a — Abwicklungs-Tabelle kompakter (Namen gekürzt, Positionen ans Ende)
Kundenname mit Ellipsis begrenzt (150px, iPad 110px; voller Name als Tooltip),
Zellen-Padding reduziert, Positionen-Toggle als schmale letzte Spalte —
zusammen mit den Aktionen rechts angepinnt, beim Scrollen bleibt beides sichtbar.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 11:56:31 +00:00
4c73e64446 Warenwirtschaft: AP-33a — Abwicklungs-Tabelle für iPad optimiert
9 → 6 Spalten (Datum unter Bestellnr., Gewicht in die Packliste, Zahlung in
die Status-Spalte); Aktionen-Spalte sticky am rechten Rand (bleibt beim
horizontalen Scrollen sichtbar); unterhalb Desktop-Breite Icon-Buttons ohne
Beschriftung (Tooltip bleibt).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 11:48:52 +00:00
054f26fb38 Warenwirtschaft: Doku — AP-33a abgeschlossen (Hinweise, Testleitfaden, Plan-Protokoll)
Inkl. dokumentationspflichtiger Regel (Kundenwunsch): WaWi-Status hat Vorrang,
Detailseiten überschreiben ihn nicht mehr automatisch.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 11:40:05 +00:00
a367d851f6 Warenwirtschaft: AP-33a Bestell-Abwicklung — Nav „Bestellungen" + Fulfillment-Board
Neuer Nav-Punkt „Bestellungen" (Abwicklung + API-Bestellungen als Unterpunkte).
Board für Versand-Mitarbeiter (copyreader): 4 Filter-Kacheln (heute eingegangen /
zu konfektionieren / versandfertig / heute versendet), Packliste je Bestellung
(Sets mit Komponenten), Dokumente (Rechnung/Lieferschein/Kombi-Download über
eigene copyreader-Route, Erstellen ohne Mailversand; API-Bestellungen verlinken
die externe Rechnung), Aktionen Konfektioniert/Versendet (nur vorwärts, Storno
bleibt Verkäufe/admin). Versandfertig-Regel per Kundenentscheid: Rechnung sofort,
Vorkasse nach Zahlungseingang, API immer (ShoppingOrder::isReadyToShip()).
Statuswechsel-Logik in OrderStatusService extrahiert (Verkäufe-Modal + Board
teilen Transaktion/Lock/Margin-Folgen/AP-13-Abzug). Kundenentscheid Punkt 3:
Board-Statuswechsel setzt shipped_status_locked — die Bestell-Detailseiten
ändern den Status dann nicht mehr automatisch (offen → in Bearbeitung).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 11:30:57 +00:00
f1eb5fbc7f Warenwirtschaft: Doku — Kundenentscheide zu AP-33 (versandfertig, Rechnungen, Status-Sperre, Rechte)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 11:20:28 +00:00
425b2a09e0 Warenwirtschaft: AP-33 (Bestell-Abwicklung: Nav „Bestellungen" + Fulfillment-Board) geplant
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>
2026-07-16 10:12:41 +00:00
c0476ebe24 Warenwirtschaft: AP-13 — Stichtags-Schutz für vor Einführung versendete Bestellungen
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>
2026-07-16 09:31:23 +00:00
f51da96354 Warenwirtschaft: Doku — Kundenentscheid Self-Shipping ohne Bestandsabzug bestätigt
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 08:56:15 +00:00
9bdf135ed9 Warenwirtschaft: Doku — AP-13 abgeschlossen (Hinweise, Testleitfaden, Plan-Protokoll)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 08:44:50 +00:00
71d5591e7b Warenwirtschaft: AP-13 API-Bestellungen — Protokoll mit SKU-Fehlermarkierung
Neuer Navigationspunkt „API-Bestellungen": jede wp/order-Übertragung wird
protokolliert (api_order_logs) — auch abgelehnte (Kunde unbekannt, Bestellung
existiert bereits, Speicherfehler). Positionen ohne Produktzuordnung
(unbekannte WP-Nummer) markieren den Eintrag rot; das Modal zeigt den Inhalt
der Übertragung je Position (SKU, Produkt, Menge, Preis, Meldung übersetzt).
Dazu SKU-Konsistenzprüfung auf der Seite: doppelte WP-Nummern aktiver Produkte
(Warnung) und aktive Produkte ohne WP-Nummer (aufklappbar). Behebt die stille
Lücke, dass „article not found" nur in der API-Antwort unterging und die
Position kommentarlos in Bestellung und Bestandsabzug fehlte (Plan §4).
ShoppingUserController per Pint formatiert.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 08:04:16 +00:00
211aeed384 Warenwirtschaft: AP-13 Shop-Bestandsabzug bei Versand (inkl. Sets)
ProductStockService::syncSaleStock(): idempotenter Differenz-Abgleich der
Verkaufs-Abgänge (source='sale', Referenz = Bestellung) mit dem Versandstatus —
Abzug je Bestellposition bei versendet/abgeschlossen, Sets rekursiv über
product_set_items in Einzelprodukte aufgelöst; Zurücksetzen/Storno führt per
Gegenbuchung zurück (behebt auch das Doppelabzug-Risiko Versand→Zurücksetzen→
Versand). Andockpunkte: SalesController::store (in der Transaktion) und
PaymentReminderService (Auto-Storno per Cron). Verbrauch/Monat zählt
Verkaufs-Abgänge automatisch mit (source != production).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 07:53:52 +00:00
6b8fcadcbf Warenwirtschaft: SalesController::store() gehärtet (Validierung, Transaktion, Lock)
Vorbereitung AP-13: Versand-Statuswechsel validiert Eingaben (Status aus
shippedTypes, Action-Whitelist), läuft in DB::transaction mit lockForUpdate
gegen Doppelklick/parallele Tabs. Verhalten sonst unverändert.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 07:44:21 +00:00
46da71ff18 Warenwirtschaft: Doku — Stand-Datum 16.07., Testleitfaden gestrafft
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-16 07:39:19 +00:00
f8956e8832 Warenwirtschaft: AP-32 (Versand mit DHL-Etiketten per API) neu aufgenommen
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>
2026-07-15 16:14:17 +00:00
f2f06f0ab9 Warenwirtschaft: AP-13-Umsetzungsansatz nach Plugin-Sichtung dokumentiert
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>
2026-07-15 16:03:20 +00:00
592b03ace5 Partnercenter-API: WooCommerce-Plugin (v1.3.3) als Referenz eingecheckt
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>
2026-07-15 15:46:16 +00:00