kunden_anlegen
Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| kunden_anlegen [2026/01/26 14:24] – angelegt pldoku | kunden_anlegen [2026/01/29 19:33] (aktuell) – gelöscht pldoku | ||
|---|---|---|---|
| Zeile 1: | Zeile 1: | ||
| - | Vorschlag: Umstrukturierung der Käufererstellung nach 3-Schichten-Architektur | ||
| - | Analyse der aktuellen Implementierung | ||
| - | Aktuelle Struktur (Buyer:: | ||
| - | Die aktuelle Buyer:: | ||
| - | Validierung (ValidateData, | ||
| - | Geschäftslogik (setAgentByEmail, | ||
| - | Datenbankzugriffe (InsertBuyer, | ||
| - | Cache-Operationen (CacheBuyers, | ||
| - | Externe Integrationen (E-Mail-Versand, | ||
| - | Orchestrierung (implizit durch die Reihenfolge der Aufrufe) | ||
| - | Vorschlag: Neue Struktur | ||
| - | Übersicht der Schichten | ||
| - | API (CustomerController) | ||
| - | ↓ | ||
| - | Orchestrierung (BuyerCreationOrchestration) | ||
| - | ↓ | ||
| - | ├─→ Business-Funktionen (Fachfunktionen) | ||
| - | │ | ||
| - | │ | ||
| - | │ | ||
| - | │ | ||
| - | │ | ||
| - | │ | ||
| - | ↓ | ||
| - | Zwischenschicht (Repositories) | ||
| - | ├─→ BuyerRepository | ||
| - | ├─→ AddressRepository | ||
| - | ├─→ BankRepository | ||
| - | ├─→ UserRepository | ||
| - | ├─→ SponsorRepository | ||
| - | ├─→ VoucherRepository | ||
| - | └─→ InterestingRepository | ||
| - | ↓ | ||
| - | Framework (Yii2) | ||
| - | Detaillierte Aufteilung | ||
| - | 1. API Layer | ||
| - | Datei: backend/ | ||
| - | |||
| - | Verantwortlichkeiten: | ||
| - | |||
| - | Empfang von HTTP-Requests | ||
| - | Validierung des Request-Formats | ||
| - | Aufruf der Orchestrierung | ||
| - | Formatierung der Response | ||
| - | Fehlerbehandlung auf API-Ebene | ||
| - | Code-Struktur: | ||
| - | |||
| - | class CustomerController extends Controller | ||
| - | { | ||
| - | public function actionCreate($request) | ||
| - | { | ||
| - | try { | ||
| - | // 1. Request-Validierung (Format, nicht Inhalt!) | ||
| - | $this-> | ||
| - | | ||
| - | // 2. Aufruf Orchestrierung | ||
| - | $orchestration = Yii:: | ||
| - | $result = $orchestration-> | ||
| - | | ||
| - | // 3. Response formatieren | ||
| - | return $this-> | ||
| - | | ||
| - | } catch (ValidationException $e) { | ||
| - | return $this-> | ||
| - | } catch (\Exception $e) { | ||
| - | return $this-> | ||
| - | } | ||
| - | } | ||
| - | } | ||
| - | Was NICHT hier: | ||
| - | |||
| - | ❌ Geschäftslogik | ||
| - | ❌ Validierung von Geschäftsdaten | ||
| - | ❌ Entscheidungen über Prozessablauf | ||
| - | 2. Orchestrierung (BuyerCreationOrchestration) | ||
| - | Datei: backend/ | ||
| - | |||
| - | Verantwortlichkeiten: | ||
| - | |||
| - | Koordination des gesamten Erstellungsprozesses | ||
| - | Aufruf der Business-Funktionen in richtiger Reihenfolge | ||
| - | Datenbeschaffung über Zwischenschicht | ||
| - | Zusammenführung der Ergebnisse | ||
| - | KEINE Geschäftsentscheidungen | ||
| - | Code-Struktur: | ||
| - | |||
| - | class BuyerCreationOrchestration | ||
| - | { | ||
| - | private $buyerRepository; | ||
| - | private $validateBuyerDataFunction; | ||
| - | private $determineSponsorFunction; | ||
| - | private $generateIdentifiersFunction; | ||
| - | private $validateAddressesFunction; | ||
| - | private $determineRegistrationSourceFunction; | ||
| - | private $validateVoucherFunction; | ||
| - | private $saveBuyerFunction; | ||
| - | private $saveAddressesFunction; | ||
| - | private $saveBankFunction; | ||
| - | private $sendEmailFunction; | ||
| - | private $cacheService; | ||
| - | private $cmpService; | ||
| - | | ||
| - | public function createBuyer($request) | ||
| - | { | ||
| - | // 1. Daten aus Request extrahieren | ||
| - | $buyerData = $this-> | ||
| - | | ||
| - | // 2. Validierung der Eingabedaten | ||
| - | $validationResult = $this-> | ||
| - | if (!$validationResult-> | ||
| - | return $this-> | ||
| - | } | ||
| - | | ||
| - | // 3. Bestimmung des Sponsors (agentid) | ||
| - | $sponsorData = $this-> | ||
| - | $buyerData-> | ||
| - | | ||
| - | // 4. Validierung Gutschein (wenn aktiviert) | ||
| - | if ($this-> | ||
| - | $voucherResult = $this-> | ||
| - | $buyerData-> | ||
| - | } | ||
| - | | ||
| - | // 5. Prüfung auf Duplikate (wenn nicht Guest) | ||
| - | if (!$buyerData-> | ||
| - | $duplicateCheck = $this-> | ||
| - | if ($duplicateCheck-> | ||
| - | return $this-> | ||
| - | } | ||
| - | } | ||
| - | | ||
| - | // 6. Automatische Erstellung aus Interessent (wenn aktiviert) | ||
| - | if ($this-> | ||
| - | $interestingData = $this-> | ||
| - | if ($interestingData) { | ||
| - | return $this-> | ||
| - | } | ||
| - | } | ||
| - | | ||
| - | // 7. Bestimmung der Registrierungsquelle (frominternet) | ||
| - | $registrationSource = $this-> | ||
| - | $buyerData-> | ||
| - | | ||
| - | // 8. Generierung von Identifikatoren | ||
| - | $identifiers = $this-> | ||
| - | $buyerData-> | ||
| - | | ||
| - | // 9. Validierung von Adressen | ||
| - | if ($buyerData-> | ||
| - | $addressValidation = $this-> | ||
| - | if (!$addressValidation-> | ||
| - | return $this-> | ||
| - | } | ||
| - | } | ||
| - | | ||
| - | // 10. Validierung Lager (wenn angegeben) | ||
| - | if ($buyerData-> | ||
| - | $warehouseValidation = $this-> | ||
| - | if (!$warehouseValidation-> | ||
| - | return $this-> | ||
| - | } | ||
| - | } | ||
| - | | ||
| - | // 11. Speicherung des Käufers | ||
| - | $savedBuyer = $this-> | ||
| - | | ||
| - | // 12. Speicherung der Adressen | ||
| - | if ($buyerData-> | ||
| - | $this-> | ||
| - | } | ||
| - | | ||
| - | // 13. Speicherung der Bankdaten | ||
| - | if ($buyerData-> | ||
| - | $this-> | ||
| - | } | ||
| - | | ||
| - | // 14. Erstellung des Benutzers (WboUser) | ||
| - | $user = $this-> | ||
| - | | ||
| - | // 15. Zusätzliche Aktionen | ||
| - | $this-> | ||
| - | | ||
| - | // 16. Cache aktualisieren | ||
| - | $this-> | ||
| - | $this-> | ||
| - | | ||
| - | // 17. Response zusammenstellen | ||
| - | return $this-> | ||
| - | } | ||
| - | | ||
| - | private function checkDuplicates($buyerData) | ||
| - | { | ||
| - | // Aufruf über Repository | ||
| - | return $this-> | ||
| - | } | ||
| - | | ||
| - | private function validateWarehouse($buyerData) | ||
| - | { | ||
| - | // Business-Funktion für Lager-Validierung | ||
| - | return $this-> | ||
| - | } | ||
| - | | ||
| - | private function createUser($buyer, | ||
| - | { | ||
| - | // Orchestrierung für User-Erstellung (kann auch eigene Orchestrierung haben) | ||
| - | $userOrchestration = Yii:: | ||
| - | return $userOrchestration-> | ||
| - | } | ||
| - | | ||
| - | private function performPostCreationActions($buyer, | ||
| - | { | ||
| - | // E-Mail-Versand (wenn nicht Guest) | ||
| - | if (!$buyerData-> | ||
| - | $this-> | ||
| - | } | ||
| - | | ||
| - | // Letter Package | ||
| - | $this-> | ||
| - | | ||
| - | // Starter zu VP konvertieren (wenn starterid vorhanden) | ||
| - | if ($buyerData-> | ||
| - | $this-> | ||
| - | } | ||
| - | | ||
| - | // CMP-Export (wenn aktiviert) | ||
| - | if ($this-> | ||
| - | $this-> | ||
| - | } | ||
| - | } | ||
| - | } | ||
| - | Was NICHT hier: | ||
| - | |||
| - | ❌ Geschäftslogik (z.B. "wenn agentid fehlt, dann..." | ||
| - | ❌ Direkte Datenbankzugriffe | ||
| - | ❌ SQL-Queries | ||
| - | ❌ Validierungsregeln | ||
| - | 3. Business-Funktionen (Fachfunktionen) | ||
| - | 3.1. ValidateBuyerDataFunction | ||
| - | Datei: backend/ | ||
| - | |||
| - | Verantwortlichkeiten: | ||
| - | |||
| - | Validierung aller Käuferdaten nach Geschäftsregeln | ||
| - | Prüfung von Pflichtfeldern | ||
| - | Format-Validierung (E-Mail, IBAN, Steuernummer, | ||
| - | Rückgabe von Validierungsergebnissen | ||
| - | Code-Struktur: | ||
| - | |||
| - | class ValidateBuyerDataFunction | ||
| - | { | ||
| - | private $emailValidator; | ||
| - | private $ibanValidator; | ||
| - | private $taxIdValidator; | ||
| - | private $usernameValidator; | ||
| - | | ||
| - | public function validate(BuyerData $buyerData): | ||
| - | { | ||
| - | $result = new ValidationResult(); | ||
| - | | ||
| - | // 1. E-Mail-Validierung | ||
| - | if ($buyerData-> | ||
| - | if (!$this-> | ||
| - | $result-> | ||
| - | } | ||
| - | } else { | ||
| - | $result-> | ||
| - | } | ||
| - | | ||
| - | // 2. Username-Validierung (wenn angegeben) | ||
| - | if ($buyerData-> | ||
| - | if (!$this-> | ||
| - | $result-> | ||
| - | } | ||
| - | } | ||
| - | | ||
| - | // 3. Steuernummer-Validierung (wenn angegeben) | ||
| - | if ($buyerData-> | ||
| - | if (!$this-> | ||
| - | $result-> | ||
| - | } | ||
| - | } | ||
| - | | ||
| - | // 4. IBAN-Validierung (wenn Bankdaten vorhanden) | ||
| - | if ($buyerData-> | ||
| - | $ibanValidation = $this-> | ||
| - | if (!$ibanValidation-> | ||
| - | $result-> | ||
| - | } | ||
| - | } | ||
| - | | ||
| - | // 5. PLZ-Validierung (wenn Adressen vorhanden) | ||
| - | if ($buyerData-> | ||
| - | $plzValidation = $this-> | ||
| - | if (!$plzValidation-> | ||
| - | $result-> | ||
| - | } | ||
| - | } | ||
| - | | ||
| - | return $result; | ||
| - | } | ||
| - | | ||
| - | private function validatePostalCodes(array $addresses): | ||
| - | { | ||
| - | $result = new ValidationResult(); | ||
| - | foreach ($addresses as $address) { | ||
| - | if (!$this-> | ||
| - | $result-> | ||
| - | } | ||
| - | } | ||
| - | return $result; | ||
| - | } | ||
| - | } | ||
| - | Was NICHT hier: | ||
| - | |||
| - | ❌ Datenbankzugriffe (nur über Interfaces/ | ||
| - | ❌ SQL-Queries | ||
| - | ❌ Framework-spezifischer Code | ||
| - | 3.2. DetermineSponsorFunction | ||
| - | Datei: backend/ | ||
| - | |||
| - | Verantwortlichkeiten: | ||
| - | |||
| - | Bestimmung des Sponsors (agentid) nach Geschäftsregeln | ||
| - | Automatische Bestimmung über E-Mail (wenn aktiviert) | ||
| - | Rückgabe des Sponsor-Ergebnisses | ||
| - | Code-Struktur: | ||
| - | |||
| - | class DetermineSponsorFunction | ||
| - | { | ||
| - | private $sponsorRepository; | ||
| - | private $buyerRepository; | ||
| - | private $config; | ||
| - | | ||
| - | public function determine(BuyerData $buyerData): | ||
| - | { | ||
| - | $result = new SponsorResult(); | ||
| - | | ||
| - | // 1. Wenn agentid bereits vorhanden → validieren | ||
| - | if ($buyerData-> | ||
| - | $sponsor = $this-> | ||
| - | if (!$sponsor || !$sponsor-> | ||
| - | throw new InvalidSponsorException(' | ||
| - | } | ||
| - | $result-> | ||
| - | $result-> | ||
| - | return $result; | ||
| - | } | ||
| - | | ||
| - | // 2. Automatische Bestimmung über E-Mail (wenn aktiviert) | ||
| - | if ($this-> | ||
| - | $sponsor = $this-> | ||
| - | if ($sponsor) { | ||
| - | $result-> | ||
| - | $result-> | ||
| - | return $result; | ||
| - | } | ||
| - | } | ||
| - | | ||
| - | // 3. Fallback auf Master-VP (Geschäftsregel) | ||
| - | $masterVP = $this-> | ||
| - | $result-> | ||
| - | $result-> | ||
| - | | ||
| - | return $result; | ||
| - | } | ||
| - | | ||
| - | private function determineByEmail(string $email): ?Sponsor | ||
| - | { | ||
| - | // Geschäftsregel: | ||
| - | $buyer = $this-> | ||
| - | if (!$buyer) { | ||
| - | return null; | ||
| - | } | ||
| - | | ||
| - | // Geschäftsregel: | ||
| - | $sponsor = $this-> | ||
| - | | ||
| - | // Geschäftsregel: | ||
| - | if ($this-> | ||
| - | // Neueste zuerst | ||
| - | return $sponsor; | ||
| - | } else { | ||
| - | // Älteste zuerst | ||
| - | return $sponsor; | ||
| - | } | ||
| - | } | ||
| - | } | ||
| - | 3.3. GenerateBuyerIdentifiersFunction | ||
| - | Datei: backend/ | ||
| - | |||
| - | Verantwortlichkeiten: | ||
| - | |||
| - | Generierung von Kundennummer (kundennr) | ||
| - | Generierung von Username | ||
| - | Generierung von Passwort (wenn nicht vorhanden) | ||
| - | Bestimmung von accounting-Nummer | ||
| - | Rückgabe aller generierten Identifikatoren | ||
| - | Code-Struktur: | ||
| - | |||
| - | class GenerateBuyerIdentifiersFunction | ||
| - | { | ||
| - | private $buyerRepository; | ||
| - | private $passwordGenerator; | ||
| - | private $usernameGenerator; | ||
| - | private $customerNumberGenerator; | ||
| - | | ||
| - | public function generate(BuyerData $buyerData): | ||
| - | { | ||
| - | $result = new IdentifierResult(); | ||
| - | | ||
| - | // 1. Kundennummer generieren | ||
| - | $customerNumber = $this-> | ||
| - | $result-> | ||
| - | | ||
| - | // 2. Username generieren | ||
| - | $username = $this-> | ||
| - | $result-> | ||
| - | | ||
| - | // 3. Passwort generieren (wenn nicht vorhanden) | ||
| - | if (!$buyerData-> | ||
| - | $password = $this-> | ||
| - | $result-> | ||
| - | } else { | ||
| - | $result-> | ||
| - | } | ||
| - | | ||
| - | // 4. Accounting-Nummer bestimmen | ||
| - | $accounting = $this-> | ||
| - | $result-> | ||
| - | | ||
| - | return $result; | ||
| - | } | ||
| - | | ||
| - | private function generateCustomerNumber(BuyerData $buyerData): | ||
| - | { | ||
| - | // Geschäftsregel 1: Wenn number angegeben → verwenden (nach Prüfung) | ||
| - | if ($buyerData-> | ||
| - | // Prüfung auf Eindeutigkeit über Repository | ||
| - | if ($this-> | ||
| - | return $buyerData-> | ||
| - | } | ||
| - | throw new CustomerNumberAlreadyExistsException(); | ||
| - | } | ||
| - | | ||
| - | // Geschäftsregel 2: Wenn mitarbeiternr vorhanden → verwenden | ||
| - | if ($buyerData-> | ||
| - | return $buyerData-> | ||
| - | } | ||
| - | | ||
| - | // Geschäftsregel 3: Automatische Generierung | ||
| - | return $this-> | ||
| - | } | ||
| - | | ||
| - | private function generateUsername(BuyerData $buyerData, string $customerNumber): | ||
| - | { | ||
| - | // Geschäftsregel: | ||
| - | if ($buyerData-> | ||
| - | return $buyerData-> | ||
| - | } | ||
| - | | ||
| - | // Geschäftsregel: | ||
| - | return $this-> | ||
| - | } | ||
| - | | ||
| - | private function determineAccountingNumber(BuyerData $buyerData, string $customerNumber): | ||
| - | { | ||
| - | // Geschäftsregel 1: Wenn emplaccounting vorhanden → verwenden | ||
| - | if ($buyerData-> | ||
| - | return $buyerData-> | ||
| - | } | ||
| - | | ||
| - | // Geschäftsregel 2: Wenn accounting vorhanden → verwenden | ||
| - | if ($buyerData-> | ||
| - | return $buyerData-> | ||
| - | } | ||
| - | | ||
| - | // Geschäftsregel 3: Fallback auf Kundennummer | ||
| - | return $customerNumber; | ||
| - | } | ||
| - | } | ||
| - | 3.4. ValidateAddressesFunction | ||
| - | Datei: backend/ | ||
| - | |||
| - | Verantwortlichkeiten: | ||
| - | |||
| - | Validierung aller Adressen | ||
| - | Prüfung auf Pflichtfelder | ||
| - | Validierung von Ländern | ||
| - | Prüfung auf Konsistenz | ||
| - | Code-Struktur: | ||
| - | |||
| - | class ValidateAddressesFunction | ||
| - | { | ||
| - | private $countryRepository; | ||
| - | private $postalCodeValidator; | ||
| - | | ||
| - | public function validate(array $addresses): | ||
| - | { | ||
| - | $result = new ValidationResult(); | ||
| - | | ||
| - | foreach ($addresses as $index => $address) { | ||
| - | // 1. Land-Validierung | ||
| - | if (!$address-> | ||
| - | $result-> | ||
| - | continue; | ||
| - | } | ||
| - | | ||
| - | $country = $this-> | ||
| - | if (!$country) { | ||
| - | $result-> | ||
| - | continue; | ||
| - | } | ||
| - | | ||
| - | // 2. PLZ-Validierung | ||
| - | if ($address-> | ||
| - | if (!$this-> | ||
| - | $result-> | ||
| - | } | ||
| - | } | ||
| - | | ||
| - | // 3. Weitere Validierungen... | ||
| - | } | ||
| - | | ||
| - | return $result; | ||
| - | } | ||
| - | } | ||
| - | 3.5. DetermineRegistrationSourceFunction | ||
| - | Datei: backend/ | ||
| - | |||
| - | Verantwortlichkeiten: | ||
| - | |||
| - | Bestimmung von frominternet basierend auf autonumbertype | ||
| - | Rückgabe der Registrierungsquelle | ||
| - | Code-Struktur: | ||
| - | |||
| - | class DetermineRegistrationSourceFunction | ||
| - | { | ||
| - | public function determine(BuyerData $buyerData): | ||
| - | { | ||
| - | // Geschäftsregel: | ||
| - | if ($buyerData-> | ||
| - | $type = $buyerData-> | ||
| - | | ||
| - | if ($type === 3) { | ||
| - | return new RegistrationSource(107, | ||
| - | } | ||
| - | | ||
| - | if ($type === 5) { | ||
| - | return new RegistrationSource(111, | ||
| - | } | ||
| - | | ||
| - | // Standard für andere autonumbertype | ||
| - | return new RegistrationSource(103, | ||
| - | } | ||
| - | | ||
| - | // Standard-Registrierungsquelle | ||
| - | return new RegistrationSource(102, | ||
| - | } | ||
| - | } | ||
| - | 3.6. ValidateVoucherFunction | ||
| - | Datei: backend/ | ||
| - | |||
| - | Verantwortlichkeiten: | ||
| - | |||
| - | Validierung von Gutschein-Code | ||
| - | Bestimmung des zugehörigen Sponsors | ||
| - | Rückgabe des Sponsor-Ergebnisses | ||
| - | Code-Struktur: | ||
| - | |||
| - | class ValidateVoucherFunction | ||
| - | { | ||
| - | private $voucherRepository; | ||
| - | private $sponsorRepository; | ||
| - | | ||
| - | public function validate(BuyerData $buyerData): | ||
| - | { | ||
| - | $result = new VoucherResult(); | ||
| - | | ||
| - | // Wenn kein agentid vorhanden → kein Gutschein-Check | ||
| - | if (!$buyerData-> | ||
| - | return $result; | ||
| - | } | ||
| - | | ||
| - | // Prüfung ob agentid ein Gutschein-Code ist | ||
| - | $voucher = $this-> | ||
| - | if (!$voucher) { | ||
| - | // Kein Gutschein → agentid bleibt unverändert | ||
| - | return $result; | ||
| - | } | ||
| - | | ||
| - | // Geschäftsregel: | ||
| - | $sponsor = $this-> | ||
| - | if (!$sponsor) { | ||
| - | throw new InvalidVoucherException(' | ||
| - | } | ||
| - | | ||
| - | // Ergebnis: agentid ersetzen, Gutschein-Code speichern | ||
| - | $result-> | ||
| - | $result-> | ||
| - | $result-> | ||
| - | | ||
| - | return $result; | ||
| - | } | ||
| - | } | ||
| - | 4. Zwischenschicht (Repositories) | ||
| - | 4.1. BuyerRepository | ||
| - | Datei: backend/ | ||
| - | |||
| - | Verantwortlichkeiten: | ||
| - | |||
| - | Alle SQL-Queries für Käufer | ||
| - | CRUD-Operationen | ||
| - | Suche nach Käufern | ||
| - | Duplikat-Prüfung | ||
| - | Code-Struktur: | ||
| - | |||
| - | class BuyerRepository implements BuyerRepositoryInterface | ||
| - | { | ||
| - | private $db; | ||
| - | | ||
| - | public function create(BuyerEntity $buyer): BuyerEntity | ||
| - | { | ||
| - | // SQL-Query hier | ||
| - | $sql = " | ||
| - | $this-> | ||
| - | | ||
| - | // Stored Procedure aufrufen | ||
| - | $this-> | ||
| - | | ||
| - | return $buyer; | ||
| - | } | ||
| - | | ||
| - | public function findById(int $id): ? | ||
| - | { | ||
| - | $sql = " | ||
| - | $row = $this-> | ||
| - | | ||
| - | if (!$row) { | ||
| - | return null; | ||
| - | } | ||
| - | | ||
| - | return $this-> | ||
| - | } | ||
| - | | ||
| - | public function findByEmail(string $email): ? | ||
| - | { | ||
| - | $sql = " | ||
| - | $row = $this-> | ||
| - | | ||
| - | if (!$row) { | ||
| - | return null; | ||
| - | } | ||
| - | | ||
| - | return $this-> | ||
| - | } | ||
| - | | ||
| - | public function isCustomerNumberAvailable(string $customerNumber): | ||
| - | { | ||
| - | $sql = " | ||
| - | $count = $this-> | ||
| - | return $count === 0; | ||
| - | } | ||
| - | | ||
| - | public function checkDuplicates(BuyerData $buyerData): | ||
| - | { | ||
| - | // Komplexe SQL-Query für Duplikat-Prüfung | ||
| - | $sql = " | ||
| - | $rows = $this-> | ||
| - | | ||
| - | return $this-> | ||
| - | } | ||
| - | | ||
| - | public function generateNewCustomerNumber(): | ||
| - | { | ||
| - | $sql = " | ||
| - | return $this-> | ||
| - | } | ||
| - | | ||
| - | private function mapToEntity(array $row): BuyerEntity | ||
| - | { | ||
| - | // Mapping von DB-Row zu Entity | ||
| - | return BuyerEntity:: | ||
| - | } | ||
| - | } | ||
| - | 4.2. AddressRepository | ||
| - | Datei: backend/ | ||
| - | |||
| - | Code-Struktur: | ||
| - | |||
| - | class AddressRepository implements AddressRepositoryInterface | ||
| - | { | ||
| - | private $db; | ||
| - | | ||
| - | public function create(int $buyerId, AddressEntity $address): AddressEntity | ||
| - | { | ||
| - | $sql = " | ||
| - | $this-> | ||
| - | | ||
| - | // Stored Procedure | ||
| - | $this-> | ||
| - | | ||
| - | return $address; | ||
| - | } | ||
| - | | ||
| - | public function update(int $addressId, AddressEntity $address): void | ||
| - | { | ||
| - | $sql = " | ||
| - | $this-> | ||
| - | | ||
| - | $this-> | ||
| - | } | ||
| - | | ||
| - | public function findMainAddress(int $buyerId): ? | ||
| - | { | ||
| - | $sql = " | ||
| - | $row = $this-> | ||
| - | | ||
| - | return $row ? $this-> | ||
| - | } | ||
| - | | ||
| - | public function findByReference(int $buyerId, string $reference): | ||
| - | { | ||
| - | $sql = " | ||
| - | $row = $this-> | ||
| - | | ||
| - | return $row ? $this-> | ||
| - | } | ||
| - | | ||
| - | public function generateNewAddressId(): | ||
| - | { | ||
| - | // Generierung neuer ID | ||
| - | $sql = " | ||
| - | return $this-> | ||
| - | } | ||
| - | } | ||
| - | 4.3. Weitere Repositories | ||
| - | BankRepository - für Bankdaten | ||
| - | UserRepository - für mlm_users und mlm_wbo_users | ||
| - | SponsorRepository - für Partner/ | ||
| - | VoucherRepository - für Gutscheine | ||
| - | InterestingRepository - für Interessenten | ||
| - | CountryRepository - für Länder | ||
| - | WarehouseRepository - für Lager | ||
| - | 5. Framework Layer | ||
| - | Bleibt unverändert: | ||
| - | |||
| - | Yii2 Framework | ||
| - | Datenbankverbindungen | ||
| - | Sicherheit | ||
| - | Routing | ||
| - | Dependency Injection Container | ||
| - | Mapping: Alte → Neue Struktur | ||
| - | Aktuelle Funktion Neue Struktur | ||
| - | Buyer:: | ||
| - | Buyer:: | ||
| - | Buyer:: | ||
| - | Buyer:: | ||
| - | Buyer:: | ||
| - | Buyer:: | ||
| - | Buyer:: | ||
| - | Buyer:: | ||
| - | Buyer:: | ||
| - | Buyer:: | ||
| - | Buyer:: | ||
| - | Cache:: | ||
| - | Direkte SQL-Queries Alle in Repositories | ||
| - | Vorteile der neuen Struktur | ||
| - | Trennung der Verantwortlichkeiten: | ||
| - | |||
| - | Geschäftslogik ist klar getrennt von Datenzugriff | ||
| - | Jede Funktion hat eine einzige Verantwortlichkeit | ||
| - | Testbarkeit: | ||
| - | |||
| - | Business-Funktionen können ohne Datenbank getestet werden | ||
| - | Repositories können isoliert getestet werden | ||
| - | Orchestrierung kann mit Mocks getestet werden | ||
| - | Wartbarkeit: | ||
| - | |||
| - | Änderungen an Geschäftsregeln → nur Business-Funktionen | ||
| - | Änderungen an Datenbankstruktur → nur Repositories | ||
| - | Framework-Wechsel → nur Repositories und API-Layer | ||
| - | Erweiterbarkeit: | ||
| - | |||
| - | Neue Geschäftsregeln → neue Business-Funktionen | ||
| - | Neue Datenquellen → neue Repository-Implementierungen | ||
| - | Framework-Unabhängigkeit: | ||
| - | |||
| - | Core (Business-Funktionen, | ||
| - | Nur Repositories und API-Layer müssen angepasst werden | ||
| - | Migrationsstrategie | ||
| - | Phase 1: Vorbereitung | ||
| - | Interfaces für alle Repositories definieren | ||
| - | Entity-Klassen erstellen | ||
| - | DTOs (Data Transfer Objects) für Request/ | ||
| - | Phase 2: Repositories extrahieren | ||
| - | SQL-Queries aus Buyer:: | ||
| - | Buyer:: | ||
| - | Phase 3: Business-Funktionen extrahieren | ||
| - | Geschäftslogik in separate Funktionen auslagern | ||
| - | Buyer:: | ||
| - | Phase 4: API-Layer anpassen | ||
| - | Controller ruft Orchestrierung auf | ||
| - | Alte Buyer:: | ||
| - | Phase 5: Cleanup | ||
| - | Alte Implementierung entfernen | ||
| - | Tests schreiben | ||
| - | Dokumentation aktualisieren | ||
| - | Beispiel: Vollständiger Ablauf | ||
| - | 1. API Request | ||
| - | POST / | ||
| - | { | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | } | ||
| - | |||
| - | 2. CustomerController:: | ||
| - | - Request formatieren | ||
| - | - BuyerCreationOrchestration aufrufen | ||
| - | |||
| - | 3. BuyerCreationOrchestration:: | ||
| - | - ValidateBuyerDataFunction aufrufen | ||
| - | - DetermineSponsorFunction aufrufen | ||
| - | - GenerateBuyerIdentifiersFunction aufrufen | ||
| - | - BuyerRepository:: | ||
| - | - AddressRepository:: | ||
| - | - UserCreationOrchestration aufrufen | ||
| - | - CacheService aufrufen | ||
| - | - Response zusammenstellen | ||
| - | |||
| - | 4. Business-Funktionen | ||
| - | - Führen Geschäftsregeln aus | ||
| - | - Rufen Repositories auf (nur lesend) | ||
| - | - Keine direkten DB-Zugriffe | ||
| - | |||
| - | 5. Repositories | ||
| - | - Führen SQL-Queries aus | ||
| - | - Mappen Daten zu Entities | ||
| - | - Keine Geschäftslogik | ||
| - | |||
| - | 6. Response | ||
| - | { | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | } | ||
| - | } | ||
| - | Zusammenfassung | ||
| - | Die neue Struktur trennt klar: | ||
| - | |||
| - | API: Request/ | ||
| - | Orchestrierung: | ||
| - | Business-Funktionen: | ||
| - | Repositories: | ||
| - | Framework: Technische Infrastruktur | ||
| - | Alle aktuellen Funktionen bleiben erhalten, sind aber klar strukturiert und testbar. | ||
kunden_anlegen.1769433845.txt.gz · Zuletzt geändert: von pldoku
