From 78f4d813f915149ddf36ba5628ec4d3d3195bcd2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Thomas=20G=C3=BCnther?=
Date: Wed, 29 Jul 2026 15:49:26 +0200
Subject: [PATCH] Configurations for payment modules
---
.../CreateTenant/CreateTenantAction.php | 3 +-
.../UpdateAvailablePaymentMethodAction.php | 2 +-
app/Enumerations/PaymentStatus.php | 24 ++++
.../AbstractEventPaymentModule.php | 118 ++++++++++++++++++
.../DTO/CreateInvoiceRequest.php | 25 ++++
.../DTO/CreateInvoiceResponse.php | 21 ++++
.../DTO/DoPaymentRequest.php | 25 ++++
.../DTO/DoPaymentResponse.php | 22 ++++
.../DTO/RegistrationSummaryRequest.php | 25 ++++
.../DTO/RegistrationSummaryResponse.php | 21 ++++
.../EventPaymentModule.php | 57 +++++++++
.../EventPaymentModuleRegistry.php | 54 ++++++++
.../Modules/AccountTransferPaymentModule.php | 38 ++++++
.../Modules/UndefinedPaymentModule.php | 33 +++++
app/Installer/ProductionDataSeeder.php | 15 ++-
app/Models/AvailablePaymentMethod.php | 2 +-
app/Models/PaymentMethod.php | 72 ++++-------
...026_07_29_140040_create_payment_status.php | 19 +++
tests/Unit/EventPaymentModuleRegistryTest.php | 59 +++++++++
19 files changed, 584 insertions(+), 51 deletions(-)
create mode 100644 app/Enumerations/PaymentStatus.php
create mode 100644 app/EventPaymentModules/AbstractEventPaymentModule.php
create mode 100644 app/EventPaymentModules/DTO/CreateInvoiceRequest.php
create mode 100644 app/EventPaymentModules/DTO/CreateInvoiceResponse.php
create mode 100644 app/EventPaymentModules/DTO/DoPaymentRequest.php
create mode 100644 app/EventPaymentModules/DTO/DoPaymentResponse.php
create mode 100644 app/EventPaymentModules/DTO/RegistrationSummaryRequest.php
create mode 100644 app/EventPaymentModules/DTO/RegistrationSummaryResponse.php
create mode 100644 app/EventPaymentModules/EventPaymentModule.php
create mode 100644 app/EventPaymentModules/EventPaymentModuleRegistry.php
create mode 100644 app/EventPaymentModules/Modules/AccountTransferPaymentModule.php
create mode 100644 app/EventPaymentModules/Modules/UndefinedPaymentModule.php
create mode 100644 database/migrations/2026_07_29_140040_create_payment_status.php
create mode 100644 tests/Unit/EventPaymentModuleRegistryTest.php
diff --git a/app/Domains/Admin/Actions/CreateTenant/CreateTenantAction.php b/app/Domains/Admin/Actions/CreateTenant/CreateTenantAction.php
index 2ea2af6..9d20ed8 100644
--- a/app/Domains/Admin/Actions/CreateTenant/CreateTenantAction.php
+++ b/app/Domains/Admin/Actions/CreateTenant/CreateTenantAction.php
@@ -31,8 +31,9 @@ class CreateTenantAction
'has_active_instance' => true,
]);
+ $paymentMethodDefaults = PaymentMethod::defaults();
foreach (PaymentMethod::all() as $paymentMethod) {
- $defaults = PaymentMethod::DEFAULTS[$paymentMethod->slug] ?? ['name' => $paymentMethod->slug, 'description' => null];
+ $defaults = $paymentMethodDefaults[$paymentMethod->slug] ?? ['name' => $paymentMethod->slug, 'description' => null];
AvailablePaymentMethod::create([
'tenant' => $tenant->slug,
diff --git a/app/Domains/Admin/Actions/UpdateAvailablePaymentMethod/UpdateAvailablePaymentMethodAction.php b/app/Domains/Admin/Actions/UpdateAvailablePaymentMethod/UpdateAvailablePaymentMethodAction.php
index 2df18b0..80b2d28 100644
--- a/app/Domains/Admin/Actions/UpdateAvailablePaymentMethod/UpdateAvailablePaymentMethodAction.php
+++ b/app/Domains/Admin/Actions/UpdateAvailablePaymentMethod/UpdateAvailablePaymentMethodAction.php
@@ -17,7 +17,7 @@ class UpdateAvailablePaymentMethodAction
$paymentMethod = $this->request->availablePaymentMethod;
$wasActive = $paymentMethod->active;
- // Nur bekannte Options-Keys übernehmen -- das Schema (PaymentMethod::OPTIONS) ist die Autorität.
+ // Nur bekannte Options-Keys übernehmen -- das Options-Schema des Zahlungsmoduls ist die Autorität.
$configuration = PaymentMethod::sanitizeConfiguration($paymentMethod->slug, $this->request->configuration);
// Guard: Aktivierung nur erlaubt, wenn alle Pflicht-Optionen befüllt sind.
diff --git a/app/Enumerations/PaymentStatus.php b/app/Enumerations/PaymentStatus.php
new file mode 100644
index 0000000..9597623
--- /dev/null
+++ b/app/Enumerations/PaymentStatus.php
@@ -0,0 +1,24 @@
+
+ */
+ public function requiredOptionKeys(): array
+ {
+ return array_values(array_map(
+ static fn (array $option) => $option['name'],
+ array_filter($this->getOptions(), static fn (array $option) => $option['required'] ?? false)
+ ));
+ }
+
+ /**
+ * Reduziert eine Konfiguration auf die im Schema definierten Options-Keys.
+ * Unbekannte Keys werden verworfen -- getOptions() ist die Autorität.
+ *
+ * @param array $config
+ * @return array
+ */
+ public function sanitizeConfiguration(array $config): array
+ {
+ $result = [];
+ foreach ($this->getOptions() as $option) {
+ if (array_key_exists($option['name'], $config)) {
+ $result[$option['name']] = $config[$option['name']];
+ }
+ }
+
+ return $result;
+ }
+
+ /**
+ * Prüft, ob alle Pflicht-Optionen befüllt (non-empty) sind.
+ *
+ * @param array $config
+ */
+ public function isConfigurationComplete(array $config): bool
+ {
+ foreach ($this->requiredOptionKeys() as $key) {
+ $value = $config[$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;
+}
diff --git a/app/EventPaymentModules/DTO/CreateInvoiceRequest.php b/app/EventPaymentModules/DTO/CreateInvoiceRequest.php
new file mode 100644
index 0000000..b1fe852
--- /dev/null
+++ b/app/EventPaymentModules/DTO/CreateInvoiceRequest.php
@@ -0,0 +1,25 @@
+ $configuration Aufgelöste (pro-Event-)Konfiguration des Moduls.
+ */
+ public function __construct(
+ public readonly Event $event,
+ public readonly EventParticipant $participant,
+ public readonly Amount $amount,
+ public readonly array $configuration = [],
+ ) {
+ }
+}
diff --git a/app/EventPaymentModules/DTO/CreateInvoiceResponse.php b/app/EventPaymentModules/DTO/CreateInvoiceResponse.php
new file mode 100644
index 0000000..ace7ac4
--- /dev/null
+++ b/app/EventPaymentModules/DTO/CreateInvoiceResponse.php
@@ -0,0 +1,21 @@
+> Gemeinsame Rechnungspositionen (Rumpf). */
+ public array $lines = [];
+
+ public ?string $closingStatement = null;
+ public ?string $message = null;
+}
diff --git a/app/EventPaymentModules/DTO/DoPaymentRequest.php b/app/EventPaymentModules/DTO/DoPaymentRequest.php
new file mode 100644
index 0000000..e46e0a9
--- /dev/null
+++ b/app/EventPaymentModules/DTO/DoPaymentRequest.php
@@ -0,0 +1,25 @@
+ $configuration Aufgelöste (pro-Event-)Konfiguration des Moduls.
+ */
+ public function __construct(
+ public readonly Event $event,
+ public readonly EventParticipant $participant,
+ public readonly Amount $amount,
+ public readonly array $configuration = [],
+ ) {
+ }
+}
diff --git a/app/EventPaymentModules/DTO/DoPaymentResponse.php b/app/EventPaymentModules/DTO/DoPaymentResponse.php
new file mode 100644
index 0000000..5dc2e48
--- /dev/null
+++ b/app/EventPaymentModules/DTO/DoPaymentResponse.php
@@ -0,0 +1,22 @@
+ $configuration Aufgelöste (pro-Event-)Konfiguration des Moduls.
+ */
+ public function __construct(
+ public readonly Event $event,
+ public readonly Amount $amount,
+ public readonly array $configuration = [],
+ ) {
+ }
+}
diff --git a/app/EventPaymentModules/DTO/RegistrationSummaryResponse.php b/app/EventPaymentModules/DTO/RegistrationSummaryResponse.php
new file mode 100644
index 0000000..1eaa4b1
--- /dev/null
+++ b/app/EventPaymentModules/DTO/RegistrationSummaryResponse.php
@@ -0,0 +1,21 @@
+ Zeilen des Zahlungs-Abschnitts. */
+ public array $lines = [];
+
+ /** Bestätigungstext für die Checkbox, z.B. "Ich bestätige, den Betrag von X zu überweisen.". */
+ public ?string $confirmationLabel = null;
+}
diff --git a/app/EventPaymentModules/EventPaymentModule.php b/app/EventPaymentModules/EventPaymentModule.php
new file mode 100644
index 0000000..c2b7390
--- /dev/null
+++ b/app/EventPaymentModules/EventPaymentModule.php
@@ -0,0 +1,57 @@
+
+ */
+ public function getOptions(): array;
+
+ /**
+ * Liefert den zahlungsspezifischen Teil der Anmelde-Zusammenfassung.
+ * (In dieser Iteration nur als Stub vorhanden.)
+ */
+ public function registrationSummary(RegistrationSummaryRequest $request): RegistrationSummaryResponse;
+
+ /**
+ * Stößt die Zahlung an (bzw. beschreibt, was zu tun ist -- z.B. Redirect, Lastschrift, manuelle Überweisung).
+ * (In dieser Iteration nur als Stub vorhanden.)
+ */
+ public function doPayment(DoPaymentRequest $request): DoPaymentResponse;
+
+ /**
+ * Erzeugt die Rechnung/Zahlungsaufforderung. Der gemeinsame Rumpf kommt aus der Basisklasse,
+ * nur der Schlusssatz variiert je Modul.
+ * (In dieser Iteration nur als Stub vorhanden.)
+ */
+ public function createInvoice(CreateInvoiceRequest $request): CreateInvoiceResponse;
+}
diff --git a/app/EventPaymentModules/EventPaymentModuleRegistry.php b/app/EventPaymentModules/EventPaymentModuleRegistry.php
new file mode 100644
index 0000000..96698ba
--- /dev/null
+++ b/app/EventPaymentModules/EventPaymentModuleRegistry.php
@@ -0,0 +1,54 @@
+ Zahlungsmodul. Neue Zahlungsarten werden hier eingetragen.
+ * Bewusst statisch + manuelle Instanziierung (kein Container-Binding), passend zum Projektstil.
+ */
+class EventPaymentModuleRegistry
+{
+ /**
+ * Alle registrierten Modul-Klassen. Reihenfolge bestimmt u.a. die Seed-Reihenfolge.
+ *
+ * @var array>
+ */
+ private const MODULES = [
+ AccountTransferPaymentModule::class,
+ UndefinedPaymentModule::class,
+ ];
+
+ /** @var array|null Lazy gecachte Instanzen (slug => Modul). */
+ private static ?array $instances = null;
+
+ /**
+ * @return array
+ */
+ public static function all(): array
+ {
+ if (self::$instances === null) {
+ self::$instances = [];
+ foreach (self::MODULES as $moduleClass) {
+ self::$instances[$moduleClass::slug()] = new $moduleClass();
+ }
+ }
+
+ return self::$instances;
+ }
+
+ public static function forSlug(string $slug): ?EventPaymentModule
+ {
+ return self::all()[$slug] ?? null;
+ }
+
+ /**
+ * @return array
+ */
+ public static function slugs(): array
+ {
+ return array_keys(self::all());
+ }
+}
diff --git a/app/EventPaymentModules/Modules/AccountTransferPaymentModule.php b/app/EventPaymentModules/Modules/AccountTransferPaymentModule.php
new file mode 100644
index 0000000..8bebb25
--- /dev/null
+++ b/app/EventPaymentModules/Modules/AccountTransferPaymentModule.php
@@ -0,0 +1,38 @@
+ 'account_owner', 'label' => 'Kontoinhaber', 'type' => 'string', 'required' => true],
+ ['name' => 'iban', 'label' => 'IBAN', 'type' => 'string', 'required' => true],
+ ['name' => 'bic', 'label' => 'BIC', 'type' => 'string', 'required' => false],
+ ];
+ }
+
+ protected function invoiceClosingStatement(CreateInvoiceRequest $request): string
+ {
+ // TODO: In einer Folge-Iteration ausformulieren (z.B. "Bitte überweise bis zum ... auf IBAN ...").
+ return '';
+ }
+}
diff --git a/app/EventPaymentModules/Modules/UndefinedPaymentModule.php b/app/EventPaymentModules/Modules/UndefinedPaymentModule.php
new file mode 100644
index 0000000..16f543d
--- /dev/null
+++ b/app/EventPaymentModules/Modules/UndefinedPaymentModule.php
@@ -0,0 +1,33 @@
+installParticipationTypes();
$this->installEfzStatus();
$this->installPaymentMethods();
+ $this->installPaymentStatus();
+ }
+
+ private function installPaymentStatus() {
+ PaymentStatus::create(['slug' => PaymentStatus::PAYMENT_STATUS_PENDING]);
+ PaymentStatus::create(['slug' => PaymentStatus::PAYMENT_STATUS_SCHEDULED]);
+ PaymentStatus::create(['slug' => PaymentStatus::PAYMENT_STATUS_PAID]);
+ PaymentStatus::create(['slug' => PaymentStatus::PAYMENT_STATUS_FAILED]);
}
private function installPaymentMethods() {
- PaymentMethod::create(['slug' => PaymentMethod::PAYMENT_ACCOUNT_TRANSACTION]);
- PaymentMethod::create(['slug' => PaymentMethod::PAYMENT_NOT_DEFINED]);
+ foreach (EventPaymentModuleRegistry::slugs() as $slug) {
+ PaymentMethod::create(['slug' => $slug]);
+ }
}
private function installEfzStatus() {
diff --git a/app/Models/AvailablePaymentMethod.php b/app/Models/AvailablePaymentMethod.php
index a8b8c27..7d03ff0 100644
--- a/app/Models/AvailablePaymentMethod.php
+++ b/app/Models/AvailablePaymentMethod.php
@@ -39,7 +39,7 @@ class AvailablePaymentMethod extends InstancedModel
}
/**
- * Sind alle Pflicht-Optionen dieses Moduls (siehe PaymentMethod::OPTIONS) befüllt?
+ * Sind alle Pflicht-Optionen dieses Moduls (siehe Options-Schema des Zahlungsmoduls) befüllt?
*/
public function isComplete(): bool
{
diff --git a/app/Models/PaymentMethod.php b/app/Models/PaymentMethod.php
index 7966ebc..addc670 100644
--- a/app/Models/PaymentMethod.php
+++ b/app/Models/PaymentMethod.php
@@ -2,12 +2,17 @@
namespace App\Models;
+use App\EventPaymentModules\EventPaymentModuleRegistry;
use App\Scopes\CommonModel;
use Illuminate\Database\Eloquent\Concerns\HasUuids;
/**
* @property string $id
* @property string $slug
+ *
+ * Hinweis: Das Verhalten je Zahlungsart (Options-Schema, Defaults, Zahlung, Rechnung) liegt in den
+ * Zahlungsmodulen unter {@see \App\EventPaymentModules}. Dieses Model bleibt eine dünne Fassade, damit
+ * bestehende Aufrufstellen (PaymentMethod::optionsFor/... ) unverändert weiterlaufen.
*/
class PaymentMethod extends CommonModel
{
@@ -19,33 +24,25 @@ class PaymentMethod extends CommonModel
public const string PAYMENT_ACCOUNT_TRANSACTION = 'PAYMENT_ACCOUNT_TRANSACTION';
public const string PAYMENT_NOT_DEFINED = 'PAYMENT_NOT_DEFINED';
- public const array DEFAULTS = [
- self::PAYMENT_ACCOUNT_TRANSACTION => ['name' => 'Überweisung auf Veranstaltungskonto', 'description' => null],
- self::PAYMENT_NOT_DEFINED => ['name' => 'Sonstiges (Barzahlung, Zahlung vor Ort)', 'description' => null],
- ];
-
- /**
- * Options-Schema je Zahlungsmodul. Definiert im Code (nicht in der DB), damit es
- * nicht mit dem Modul-Code auseinanderdriftet. In der DB stehen nur die Werte
- * (configuration-JSON auf available_payment_methods bzw. event_payment_methods).
- *
- * Jede Option: ['name' => string, 'label' => string, 'type' => string, 'required' => bool]
- *
- * @var array>
- */
- public const array OPTIONS = [
- self::PAYMENT_ACCOUNT_TRANSACTION => [
- ['name' => 'account_owner', 'label' => 'Kontoinhaber', 'type' => 'string', 'required' => true],
- ['name' => 'iban', 'label' => 'IBAN', 'type' => 'string', 'required' => true],
- ['name' => 'bic', 'label' => 'BIC', 'type' => 'string', 'required' => false],
- ],
- self::PAYMENT_NOT_DEFINED => [],
- ];
-
protected $fillable = [
'slug',
];
+ /**
+ * Standard-Werte (name/description) je Slug -- aus den Zahlungsmodulen aufgebaut.
+ *
+ * @return array
+ */
+ public static function defaults(): array
+ {
+ $defaults = [];
+ foreach (EventPaymentModuleRegistry::all() as $slug => $module) {
+ $defaults[$slug] = ['name' => $module->defaultName(), 'description' => $module->defaultDescription()];
+ }
+
+ return $defaults;
+ }
+
/**
* Options-Schema für einen Slug.
*
@@ -53,7 +50,7 @@ class PaymentMethod extends CommonModel
*/
public static function optionsFor(string $slug): array
{
- return self::OPTIONS[$slug] ?? [];
+ return EventPaymentModuleRegistry::forSlug($slug)?->getOptions() ?? [];
}
/**
@@ -63,45 +60,28 @@ class PaymentMethod extends CommonModel
*/
public static function requiredOptionKeys(string $slug): array
{
- return array_values(array_map(
- static fn (array $option) => $option['name'],
- array_filter(self::optionsFor($slug), static fn (array $option) => $option['required'] ?? false)
- ));
+ return EventPaymentModuleRegistry::forSlug($slug)?->requiredOptionKeys() ?? [];
}
/**
- * Reduziert eine Konfiguration auf die im Code definierten Options-Keys des Slugs.
- * Unbekannte Keys werden verworfen -- das Schema (self::OPTIONS) ist die Autorität.
+ * Reduziert eine Konfiguration auf die im Schema definierten Options-Keys des Slugs.
*
* @param array $config
* @return array
*/
public static function sanitizeConfiguration(string $slug, array $config): array
{
- $result = [];
- foreach (self::optionsFor($slug) as $option) {
- if (array_key_exists($option['name'], $config)) {
- $result[$option['name']] = $config[$option['name']];
- }
- }
-
- return $result;
+ return EventPaymentModuleRegistry::forSlug($slug)?->sanitizeConfiguration($config) ?? [];
}
/**
* Prüft, ob alle Pflicht-Optionen eines Slugs in der Konfiguration befüllt (non-empty) sind.
+ * Unbekannte Slugs (kein Modul) gelten als vollständig -- kein Modul, keine Pflichtfelder.
*
* @param array $config
*/
public static function isConfigurationComplete(string $slug, array $config): bool
{
- foreach (self::requiredOptionKeys($slug) as $key) {
- $value = $config[$key] ?? null;
- if ($value === null || $value === '' || $value === []) {
- return false;
- }
- }
-
- return true;
+ return EventPaymentModuleRegistry::forSlug($slug)?->isConfigurationComplete($config) ?? true;
}
}
diff --git a/database/migrations/2026_07_29_140040_create_payment_status.php b/database/migrations/2026_07_29_140040_create_payment_status.php
new file mode 100644
index 0000000..b7bb218
--- /dev/null
+++ b/database/migrations/2026_07_29_140040_create_payment_status.php
@@ -0,0 +1,19 @@
+string('slug')->primary();
+ $table->timestamps();
+ });
+ }
+
+ public function down(): void
+ {
+ Schema::dropIfExists('payment_status');
+ }
+};
diff --git a/tests/Unit/EventPaymentModuleRegistryTest.php b/tests/Unit/EventPaymentModuleRegistryTest.php
new file mode 100644
index 0000000..80449aa
--- /dev/null
+++ b/tests/Unit/EventPaymentModuleRegistryTest.php
@@ -0,0 +1,59 @@
+assertInstanceOf(
+ AccountTransferPaymentModule::class,
+ EventPaymentModuleRegistry::forSlug(PaymentMethod::PAYMENT_ACCOUNT_TRANSACTION)
+ );
+ $this->assertInstanceOf(
+ UndefinedPaymentModule::class,
+ EventPaymentModuleRegistry::forSlug(PaymentMethod::PAYMENT_NOT_DEFINED)
+ );
+ }
+
+ public function test_for_slug_returns_null_for_unknown(): void
+ {
+ $this->assertNull(EventPaymentModuleRegistry::forSlug('DOES_NOT_EXIST'));
+ }
+
+ public function test_slugs_lists_all_registered_modules(): void
+ {
+ $slugs = EventPaymentModuleRegistry::slugs();
+
+ $this->assertContains(PaymentMethod::PAYMENT_ACCOUNT_TRANSACTION, $slugs);
+ $this->assertContains(PaymentMethod::PAYMENT_NOT_DEFINED, $slugs);
+ }
+
+ public function test_module_option_helpers(): void
+ {
+ $module = new AccountTransferPaymentModule();
+
+ $this->assertSame(['account_owner', 'iban'], $module->requiredOptionKeys());
+ // Rückgabe folgt der Schema-Reihenfolge, unbekannte Keys werden verworfen.
+ $this->assertSame(
+ ['account_owner' => 'Kasse', 'iban' => 'DE123'],
+ $module->sanitizeConfiguration(['iban' => 'DE123', 'account_owner' => 'Kasse', 'evil' => 'x'])
+ );
+ $this->assertFalse($module->isConfigurationComplete(['iban' => 'DE123']));
+ $this->assertTrue($module->isConfigurationComplete(['iban' => 'DE123', 'account_owner' => 'Kasse']));
+ }
+
+ public function test_defaults_are_built_from_modules(): void
+ {
+ $defaults = PaymentMethod::defaults();
+
+ $this->assertSame('Überweisung auf Veranstaltungskonto', $defaults[PaymentMethod::PAYMENT_ACCOUNT_TRANSACTION]['name']);
+ $this->assertArrayHasKey(PaymentMethod::PAYMENT_NOT_DEFINED, $defaults);
+ }
+}