177 lines
6.0 KiB
PHP
177 lines
6.0 KiB
PHP
<?php
|
|
|
|
namespace App\EventPaymentModules;
|
|
|
|
use App\Enumerations\PaymentStatus;
|
|
use App\EventPaymentModules\DTO\CreateInvoiceRequest;
|
|
use App\EventPaymentModules\DTO\CreateInvoiceResponse;
|
|
use App\EventPaymentModules\DTO\DoPaymentRequest;
|
|
use App\EventPaymentModules\DTO\DoPaymentResponse;
|
|
use App\EventPaymentModules\DTO\RegistrationSummaryRequest;
|
|
use App\EventPaymentModules\DTO\RegistrationSummaryResponse;
|
|
|
|
/**
|
|
* Gemeinsame Basis aller Zahlungsmodule. Hält den geteilten Code und die aus {@see getOptions()}
|
|
* abgeleiteten Options-Helfer; konkrete Module definieren nur ihre Identität, ihr Options-Schema
|
|
* und -- später -- die je Zahlungsart variierenden Teile (z.B. den Rechnungs-Schlusssatz).
|
|
*/
|
|
abstract class AbstractEventPaymentModule implements EventPaymentModule
|
|
{
|
|
public function defaultDescription(): ?string
|
|
{
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Standard-Konfiguration beim Anlegen der Tenant-Instanz. Standard: leer.
|
|
*
|
|
* @return array<string, mixed>
|
|
*/
|
|
public function defaultConfiguration(): array
|
|
{
|
|
return [];
|
|
}
|
|
|
|
/**
|
|
* Payer-seitige Eingaben, die eine Zahlungsart vom Teilnehmer benötigt (z.B. später SEPA-IBAN,
|
|
* PayPal-Mail). Standard: keine. Gleiche Form wie getOptions(): [{name,label,type,required}].
|
|
*
|
|
* @return array<int, array{name: string, label: string, type: string, required: bool}>
|
|
*/
|
|
public function getParticipantOptions(): array
|
|
{
|
|
return [];
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------------------
|
|
// Aus dem jeweiligen Schema abgeleitete Helfer (Admin-Config = getOptions(),
|
|
// Teilnehmer-Eingaben = getParticipantOptions()).
|
|
// -----------------------------------------------------------------------------------------
|
|
|
|
/** @return array<int, string> */
|
|
public function requiredOptionKeys(): array
|
|
{
|
|
return $this->requiredKeys($this->getOptions());
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $config
|
|
* @return array<string, mixed>
|
|
*/
|
|
public function sanitizeConfiguration(array $config): array
|
|
{
|
|
return $this->sanitizeAgainst($this->getOptions(), $config);
|
|
}
|
|
|
|
/** @param array<string, mixed> $config */
|
|
public function isConfigurationComplete(array $config): bool
|
|
{
|
|
return $this->allRequiredFilled($this->getOptions(), $config);
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $input
|
|
* @return array<string, mixed>
|
|
*/
|
|
public function sanitizeParticipantOptions(array $input): array
|
|
{
|
|
return $this->sanitizeAgainst($this->getParticipantOptions(), $input);
|
|
}
|
|
|
|
/** @param array<string, mixed> $input */
|
|
public function participantOptionsComplete(array $input): bool
|
|
{
|
|
return $this->allRequiredFilled($this->getParticipantOptions(), $input);
|
|
}
|
|
|
|
/**
|
|
* @param array<int, array{name: string, required?: bool}> $schema
|
|
* @return array<int, string>
|
|
*/
|
|
private function requiredKeys(array $schema): array
|
|
{
|
|
return array_values(array_map(
|
|
static fn (array $option) => $option['name'],
|
|
array_filter($schema, static fn(array $option) => $option['required'] ?? false)
|
|
));
|
|
}
|
|
|
|
/**
|
|
* Reduziert Eingaben auf die im Schema definierten Keys (unbekannte werden verworfen).
|
|
*
|
|
* @param array<int, array{name: string}> $schema
|
|
* @param array<string, mixed> $input
|
|
* @return array<string, mixed>
|
|
*/
|
|
private function sanitizeAgainst(array $schema, array $input): array
|
|
{
|
|
$result = [];
|
|
foreach ($schema as $option) {
|
|
if (array_key_exists($option['name'], $input)) {
|
|
$result[$option['name']] = $input[$option['name']];
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
/**
|
|
* Sind alle Pflichtfelder des Schemas befüllt (non-empty)?
|
|
*
|
|
* @param array<int, array{name: string, required?: bool}> $schema
|
|
* @param array<string, mixed> $input
|
|
*/
|
|
private function allRequiredFilled(array $schema, array $input): bool
|
|
{
|
|
foreach ($this->requiredKeys($schema) as $key) {
|
|
$value = $input[$key] ?? null;
|
|
if ($value === null || $value === '' || $value === []) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------------------
|
|
// Operative Methoden -- in dieser Iteration bewusst als Stubs.
|
|
// -----------------------------------------------------------------------------------------
|
|
|
|
public function registrationSummary(RegistrationSummaryRequest $request): RegistrationSummaryResponse
|
|
{
|
|
// TODO: In einer Folge-Iteration ausformulieren (zahlungsspezifischer Teil der Zusammenfassung).
|
|
return new RegistrationSummaryResponse();
|
|
}
|
|
|
|
public function doPayment(DoPaymentRequest $request): DoPaymentResponse
|
|
{
|
|
// TODO: In einer Folge-Iteration ausformulieren. Default: nichts aktiv anzustoßen (Status offen).
|
|
$response = new DoPaymentResponse();
|
|
$response->success = true;
|
|
$response->status = PaymentStatus::PAYMENT_STATUS_PENDING;
|
|
|
|
return $response;
|
|
}
|
|
|
|
/**
|
|
* Template-Method: Der gemeinsame Rechnungs-Rumpf wird hier gebaut, der variierende Schlusssatz
|
|
* kommt aus {@see invoiceClosingStatement()} des jeweiligen Moduls.
|
|
*/
|
|
public function createInvoice(CreateInvoiceRequest $request): CreateInvoiceResponse
|
|
{
|
|
$response = new CreateInvoiceResponse();
|
|
// TODO: In einer Folge-Iteration den gemeinsamen Rumpf (Betrag, Leistung, Teilnehmerdaten) befüllen
|
|
// und an die Invoice-Domain anbinden.
|
|
$response->success = true;
|
|
$response->closingStatement = $this->invoiceClosingStatement($request);
|
|
|
|
return $response;
|
|
}
|
|
|
|
/**
|
|
* Der je Zahlungsart variierende Schlusssatz der Rechnung
|
|
* ("Bitte überweise bis ..." / "wird abgebucht ..." / "wurde per PayPal beglichen").
|
|
*/
|
|
abstract protected function invoiceClosingStatement(CreateInvoiceRequest $request): string;
|
|
}
|