10-04-2026
This commit is contained in:
parent
4d6b4930b2
commit
4bb89aad8c
836 changed files with 52961 additions and 5950 deletions
|
|
@ -1,9 +1,9 @@
|
|||
# Entwicklungsplan: B2In / Local for Local Marktplatz-Ökosystem
|
||||
# Entwicklungsplan: B2in / Local for Local Marktplatz-Ökosystem
|
||||
|
||||
**Erstellt:** 12.02.2026
|
||||
**Letzte Aktualisierung:** 12.02.2026
|
||||
**Basis:** konzeption.md (Version 1.1)
|
||||
**Status:** Phase 1 ✅, Phase 2 ✅, Phase 2.5 Produkt-Bearbeitung ✅, Phase 2.6 Refactoring & UX ✅, Phase 2.7 Admin-Produktverwaltung & Freigabe ✅, Phase 3 Kern ✅
|
||||
**Status:** Phase 1 ✅, Phase 2 ✅, Phase 2.5 Produkt-Bearbeitung ✅, Phase 2.6 Refactoring & UX ✅, Phase 2.7 Admin-Produktverwaltung & Freigabe ✅, Phase 3 Kern ✅, Phase 2.8 Partner-Präsentation ✅
|
||||
**Docker** Projekt läuft in Docker, root /var/www/html nutze php artisan ... nicht vendor/bin/sail artisan ...
|
||||
---
|
||||
|
||||
|
|
@ -581,6 +581,31 @@ Alle Preistypen erlaubt; Standard-Varianten mit Festpreis möglich.
|
|||
- [ ] Notification an Händler/Hersteller bei Freigabe/Ablehnung – ausstehend
|
||||
- [ ] Admin kann `product_type` bei Bedarf nachträglich ändern – ausstehend
|
||||
|
||||
#### 2.4a Nachbesserungen Phase 2 – ✅ Abgeschlossen (27.02.2026)
|
||||
|
||||
**Fix: `curate products` Permission fehlte in der Datenbank**
|
||||
- Die Permission war im `RoleSeeder` definiert, aber nie in die Produktions-DB eingespielt
|
||||
- `Attempt to read property "id" on null` beim Öffnen von `/admin/products`
|
||||
- Lösung: Migration `2026_02_27_154145_add_curate_products_permission.php`
|
||||
- `Permission::firstOrCreate(['name' => 'curate products', 'guard_name' => 'web'])`
|
||||
- Admin-Rolle bekommt Permission via `Role::where('name', 'Admin')->first()` (kein `findByName` = würde Exception werfen wenn Rolle fehlt)
|
||||
- Tests (`ProductCurationTest`, `ProductPolicyTest`, `PartnerPolicyTest`): `Permission::create()` → `Permission::firstOrCreate()` (verhindert Fehler wenn Migration die Permission bereits angelegt hat)
|
||||
|
||||
**Fix: Admin kann Produkte anlegen (Partner-Selector)**
|
||||
- Admin hat keine eigene `partner_id` → `$user->partner` war `null` → Crash beim Speichern
|
||||
- Lösung in `form-teaser.blade.php` und `form-standard.blade.php`:
|
||||
- Neues Property `$selectedPartnerId` + `resolvePartner()` Methode
|
||||
- Für Admins: Partner-Auswahl-Karte erscheint vor dem Formular (nur bei Neuanlage)
|
||||
- `updatedSelectedPartnerId()` aktualisiert Produktnummer automatisch nach Partnerwahl
|
||||
- Validierung: `selectedPartnerId` Pflichtfeld für Admins bei Neuanlage
|
||||
- Alle bestehenden 158 Produkt-Tests weiterhin grün ✅
|
||||
|
||||
**Fix: Portal Textarea Dark-Mode Kontrast**
|
||||
- Korrektur-Textfeld in der Kuration zeigte weißen Text auf weißem Hintergrund
|
||||
- Ursache: `@apply dark:text-zinc-500` innerhalb von `::placeholder` Pseudo-Elementen kompiliert in Tailwind v4 zu ungültigem `:is():where(.dark,.dark *)` Selektor
|
||||
- Lösung in `resources/css/portal.css`: Explizites CSS mit `:where(.dark,.dark *)` als Vorfahren-Selektor statt `@apply dark:`
|
||||
- Portal-Build (`npm run build:portal`) aktualisiert
|
||||
|
||||
#### 2.5 Tests Phase 2 – ✅ Kern abgeschlossen
|
||||
- [x] Feature-Tests: `PartnerPolicyTest` (10 Tests) – viewAny, view, update, curateProducts
|
||||
- [x] Feature-Tests: `ProductPolicyTest` (14 Tests) – alle Policy-Methoden
|
||||
|
|
@ -596,6 +621,59 @@ Alle Preistypen erlaubt; Standard-Varianten mit Festpreis möglich.
|
|||
|
||||
---
|
||||
|
||||
### Phase 2.8: Partner-Präsentation & Selbst-Service-Profil – ✅ ABGESCHLOSSEN (27.02.2026)
|
||||
**Geschätzter Aufwand:** 2-3 Tage | **Tatsächlich:** 1 Sitzung
|
||||
|
||||
#### 2.8.1 Händler-Profil (Retailer) – Präsentation
|
||||
- [x] `my-data.blade.php` erweitert um:
|
||||
- [x] **Story-Text** – Freitext max. 2000 Zeichen mit Live-Zeichenzähler, Feld: `story_text`
|
||||
- [x] **Öffnungszeiten** – 7-Tage-Eingabe (Mo–So), `open`/`close`-Felder + "Geschlossen"-Checkbox, Feld: `opening_hours` (JSON)
|
||||
- [x] **Spezialisierungen** – kommagetrennte Eingabe → gespeichert als JSON-Array, Feld: `specialties`
|
||||
- [x] **Gründungsjahr** – Zahlfeld mit Validierung (1800–heute), Feld: `founded_year`
|
||||
- [x] **Team-Fotos** – Mehrfach-Upload via `WithFileUploads`, gespeichert als `Media.type = 'team_photo'`
|
||||
- [x] **Showroom-Galerie** – Mehrfach-Upload, `Media.type = 'showroom'`
|
||||
- [x] Foto-Löschen per Klick (mit `wire:confirm`)
|
||||
- [x] Formular in 4 separate `flux:card`-Abschnitte gegliedert: Stammdaten, Präsentation & Story, Öffnungszeiten, Fotos
|
||||
|
||||
#### 2.8.2 Hersteller-Profil (Manufacturer) – Firma & Marke
|
||||
- [x] `my-data.blade.php` erweitert um:
|
||||
- [x] **Story-Text** – Unternehmensgeschichte, Feld: `story_text`
|
||||
- [x] **Gründungsjahr** – Feld: `founded_year`
|
||||
- [x] **Spezialisierungen** – Feld: `specialties`
|
||||
- [x] **Marken-Bilder** – Mehrfach-Upload, `Media.type = 'brand_image'`
|
||||
- [x] Abschnitte: Stammdaten, Über das Unternehmen, Marke (mit Markenname, Beschreibung, Bilder)
|
||||
|
||||
#### 2.8.3 Öffentliches Partnerprofil (`livewire/partner/profile.blade.php`)
|
||||
- [x] Story-Text anzeigen wenn vorhanden (bereits vorhanden)
|
||||
- [x] Öffnungszeiten anzeigen (bereits vorhanden)
|
||||
- [x] Spezialisierungen + Gründungsjahr anzeigen (bereits vorhanden)
|
||||
- [x] **Showroom-Galerie** – 3-spaltige Bild-Galerie unterhalb der Story
|
||||
- [x] **Marken-Bilder** (Hersteller) – 3-spaltige Galerie unter der Story
|
||||
- [x] **Team-Fotos** – 2-spaltige Galerie in der rechten Sidebar
|
||||
|
||||
#### 2.8.4 Datenbank
|
||||
- [x] Alle Felder vorhanden: `story_text`, `opening_hours`, `specialties`, `founded_year` (Migration `2026_02_12_000003_add_profile_fields_to_partners_table`)
|
||||
- [x] Media-System: Custom `Media` Model mit `type`-Feld (kein Spatie) – `Partner::media()` morph-Relation bereits vorhanden
|
||||
|
||||
#### 2.8.5 Tests Phase 2.8
|
||||
- [x] `PartnerSelfServiceProfileTest` (15 Tests) – alle bestanden ✅
|
||||
- Händler kann Story, Öffnungszeiten, Spezialisierungen, Gründungsjahr speichern
|
||||
- Händler kann Team-Fotos und Showroom-Fotos hochladen
|
||||
- Händler kann Foto löschen
|
||||
- Hersteller kann Story, Markendaten, Gründungsjahr speichern
|
||||
- Hersteller kann Marken-Bilder hochladen
|
||||
- Öffentliches Profil zeigt Story und Spezialisierungen an
|
||||
- Validierung: Story-Text max. 2000 Zeichen, Gründungsjahr-Grenzen
|
||||
|
||||
**Erstellte/geänderte Dateien (2):**
|
||||
|
||||
| Datei | Änderungen |
|
||||
|-------|-----------|
|
||||
| `resources/views/livewire/partner/my-data.blade.php` | Komplett überarbeitet: 4 Karten-Abschnitte, neue Profil-Felder, Foto-Upload mit `WithFileUploads` |
|
||||
| `resources/views/livewire/partner/profile.blade.php` | Showroom-Galerie, Marken-Bilder, Team-Fotos hinzugefügt; `media` eager-loaded |
|
||||
|
||||
---
|
||||
|
||||
### Phase 3: Kunden-Frontend & Local Feed – ✅ KERN ABGESCHLOSSEN (12.02.2026)
|
||||
**Geschätzter Aufwand:** 4-5 Tage | **Tatsächlich:** 1 Tag (12.02.2026)
|
||||
**Priorität:** HOCH – Kunden-Facing Funktionalität
|
||||
|
|
@ -721,7 +799,7 @@ Enum: App\Enums\TransactionStatus
|
|||
- [ ] `PendingMerchant` – Beleg hochgeladen, Händler muss bestätigen
|
||||
- [ ] `Confirmed` – Händler hat bestätigt → Rechnung an Händler generieren
|
||||
- [ ] `Invoiced` – Rechnung erstellt → Zahlung ausstehend
|
||||
- [ ] `Paid` – Händler hat Provision an B2In überwiesen
|
||||
- [ ] `Paid` – Händler hat Provision an B2in überwiesen
|
||||
- [ ] `Distributed` – Provisionen an Makler/Kunde ausgeschüttet
|
||||
- [ ] `Rejected` – Händler hat abgelehnt
|
||||
- [ ] `Disputed` – Streitfall
|
||||
|
|
@ -778,7 +856,7 @@ Migration: create_ledger_entries_table
|
|||
#### 6.2 Provisions-Berechnung
|
||||
- [ ] Service: `App\Services\CommissionService`
|
||||
- `calculateSplit(Transaction $transaction): CommissionSplit`
|
||||
- Berechnet: Makler-Anteil, Kunden-Cashback, B2In-Marge
|
||||
- Berechnet: Makler-Anteil, Kunden-Cashback, B2in-Marge
|
||||
- Nutzt `partner.provision_rate_percentage` und `partner.provision_fixed_amount`
|
||||
- [ ] Event Listener für `TransactionPaid`:
|
||||
- Erstellt Ledger-Einträge
|
||||
|
|
@ -856,7 +934,7 @@ Migration: create_ledger_entries_table
|
|||
> **Entscheidung:** Individuell pro Partner. Admin-Settings-Seite mit Feldern für:
|
||||
> - Makler-Provision (%)
|
||||
> - Kunden-Cashback (%)
|
||||
> - B2In-Marge (Rest)
|
||||
> - B2in-Marge (Rest)
|
||||
> Felder werden pro Partner im Admin-Backend konfiguriert.
|
||||
|
||||
**Frage 8: Ticket-Gültigkeit** ✅
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue