From 4934032ebc4282941e2734b9bf3513b6116013e2 Mon Sep 17 00:00:00 2001 From: Marc van der Meulen Date: Mon, 6 Nov 2023 11:26:18 +0100 Subject: [PATCH] Implement Financials Api --- src/Api/FinancialApi.php | 67 ++++++++++++ src/Domain/ExchangeRates.php | 28 +++++ src/Domain/Transaction.php | 75 +++++++++++++ src/Domain/TransactionCollection.php | 31 ++++++ src/RealtimeRegister.php | 4 + .../Clients/FinancialApiExchangeRatesTest.php | 27 +++++ .../FinancialApiGetTransactionTest.php | 27 +++++ .../FinancialApiListTransactionsTest.php | 102 ++++++++++++++++++ tests/Domain/data/exchangerates_valid.php | 8 ++ tests/Domain/data/transaction_valid.php | 20 ++++ 10 files changed, 389 insertions(+) create mode 100644 src/Api/FinancialApi.php create mode 100644 src/Domain/ExchangeRates.php create mode 100644 src/Domain/Transaction.php create mode 100644 src/Domain/TransactionCollection.php create mode 100644 tests/Clients/FinancialApiExchangeRatesTest.php create mode 100644 tests/Clients/FinancialApiGetTransactionTest.php create mode 100644 tests/Clients/FinancialApiListTransactionsTest.php create mode 100644 tests/Domain/data/exchangerates_valid.php create mode 100644 tests/Domain/data/transaction_valid.php diff --git a/src/Api/FinancialApi.php b/src/Api/FinancialApi.php new file mode 100644 index 0000000..4e0ab03 --- /dev/null +++ b/src/Api/FinancialApi.php @@ -0,0 +1,67 @@ +client->get(sprintf('v2/billing/financialtransactions/%d', $transactionId)); + return Transaction::fromArray($response->json()); + } + + /** + * @see https://dm.realtimeregister.com/docs/api/transactions/list + * + * @param int|null $limit + * @param int|null $offset + * @param string|null $search + * @param array $parameters + * + * @return TransactionCollection + */ + public function listTransactions( + ?int $limit = null, + ?int $offset = null, + ?string $search = null, + ?array $parameters = null + ): TransactionCollection { + $query = []; + if (! is_null($limit)) { + $query['limit'] = $limit; + } + if (! is_null($offset)) { + $query['offset'] = $offset; + } + if (! is_null($search)) { + $query['q'] = $search; + } + if (! is_null($parameters)) { + $query = array_merge($parameters, $query); + } + + $response = $this->client->get('v2/billing/financialtransactions', $query); + + return TransactionCollection::fromArray($response->json()); + } + + /* @see https://dm.realtimeregister.com/docs/api/exchangerates */ + public function exchangeRates(string $currency): ExchangeRates + { + $response = $this->client->get("v2/exchangerates/{$currency}"); + return ExchangeRates::fromArray($response->json()); + } +} diff --git a/src/Domain/ExchangeRates.php b/src/Domain/ExchangeRates.php new file mode 100644 index 0000000..9deb9bb --- /dev/null +++ b/src/Domain/ExchangeRates.php @@ -0,0 +1,28 @@ + $this->currency, + 'exchangerates' => $this->exchangerates ?? null, + ], function ($x) { + return ! is_null($x); + }); + } +} diff --git a/src/Domain/Transaction.php b/src/Domain/Transaction.php new file mode 100644 index 0000000..b6a0d54 --- /dev/null +++ b/src/Domain/Transaction.php @@ -0,0 +1,75 @@ +|null */ + public ?array $chargesPerAccount, + public ?BillableCollection $billables + ) { + } + + public function toArray(): array + { + return array_filter( + [ + 'id' => $this->id, + 'customer' => $this->customer, + 'date' => $this->date->format('Y-m-d\TH:i:s\Z'), + 'amount' => $this->amount, + 'currency' => $this->currency, + 'processId' => $this->processId, + 'processType' => $this->processType, + 'processIdentifier' => $this->processIdentifier, + 'processAction' => $this->processAction, + 'chargesPerAccount' => $this->chargesPerAccount, + 'billables' => $this->billables?->toArray(), + ], + static function ($x) { + return ! is_null($x); + } + ); + } + + /** + * @throws Exception + */ + public static function fromArray(array $json): Transaction + { + if (array_key_exists('chargesPerAccount', $json)) { + Assert::isArray($json['chargesPerAccount']); + } + + return new Transaction( + id: $json['id'], + customer: $json['customer'], + date: new DateTimeImmutable($json['date']), + amount: $json['amount'], + currency: $json['currency'], + processId: $json['processId'], + processType: $json['processType'], + processIdentifier: $json['processIdentifier'], + processAction: $json['processAction'], + chargesPerAccount: $json['chargesPerAccount'] ?? null, + billables: isset($json['billables']) ? BillableCollection::fromArray($json['billables']) : null + ); + } +} diff --git a/src/Domain/TransactionCollection.php b/src/Domain/TransactionCollection.php new file mode 100644 index 0000000..f48153e --- /dev/null +++ b/src/Domain/TransactionCollection.php @@ -0,0 +1,31 @@ +entities[$offset] ?? null; + } + + /** + * @throws Exception + */ + public static function parseChild(array $json): Transaction + { + return Transaction::fromArray($json); + } +} diff --git a/src/RealtimeRegister.php b/src/RealtimeRegister.php index 016b9e4..03d7558 100644 --- a/src/RealtimeRegister.php +++ b/src/RealtimeRegister.php @@ -9,6 +9,7 @@ use SandwaveIo\RealtimeRegister\Api\CustomersApi; use SandwaveIo\RealtimeRegister\Api\DnsTemplatesApi; use SandwaveIo\RealtimeRegister\Api\DomainsApi; +use SandwaveIo\RealtimeRegister\Api\FinancialApi; use SandwaveIo\RealtimeRegister\Api\NotificationsApi; use SandwaveIo\RealtimeRegister\Api\ProcessesApi; use SandwaveIo\RealtimeRegister\Api\ProvidersApi; @@ -39,6 +40,8 @@ final class RealtimeRegister public TLDsApi $tlds; + public FinancialApi $financial; + public function __construct( string $apiKey, ?string $baseUrl = null, @@ -60,5 +63,6 @@ public function setClient(AuthorizedClient $client): void $this->providers = new ProvidersApi($client); $this->dnstemplates = new DnsTemplatesApi($client); $this->tlds = new TLDsApi($client); + $this->financial = new FinancialApi($client); } } diff --git a/tests/Clients/FinancialApiExchangeRatesTest.php b/tests/Clients/FinancialApiExchangeRatesTest.php new file mode 100644 index 0000000..1defc04 --- /dev/null +++ b/tests/Clients/FinancialApiExchangeRatesTest.php @@ -0,0 +1,27 @@ +financial->exchangeRates('EUR'); + $this->assertInstanceOf(ExchangeRates::class, $response); + } +} diff --git a/tests/Clients/FinancialApiGetTransactionTest.php b/tests/Clients/FinancialApiGetTransactionTest.php new file mode 100644 index 0000000..5279725 --- /dev/null +++ b/tests/Clients/FinancialApiGetTransactionTest.php @@ -0,0 +1,27 @@ +financial->getTransaction(654563); + $this->assertInstanceOf(Transaction::class, $response); + } +} diff --git a/tests/Clients/FinancialApiListTransactionsTest.php b/tests/Clients/FinancialApiListTransactionsTest.php new file mode 100644 index 0000000..ad19043 --- /dev/null +++ b/tests/Clients/FinancialApiListTransactionsTest.php @@ -0,0 +1,102 @@ + [ + include __DIR__ . '/../Domain/data/transaction_valid.php', + include __DIR__ . '/../Domain/data/transaction_valid.php', + include __DIR__ . '/../Domain/data/transaction_valid.php', + ], + 'pagination' => [ + 'total' => 3, + 'offset' => 0, + 'limit' => 10, + ], + ] + ); + Assert::string($responseBody); + $sdk = MockedClientFactory::makeSdk( + 200, + $responseBody, + MockedClientFactory::assertRoute('GET', 'v2/billing/financialtransactions', $this) + ); + + $sdk->financial->listTransactions(); + } + + public function test_list_with_queries(): void + { + /** @var string $responseBody */ + $responseBody = json_encode( + [ + 'entities' => [ + include __DIR__ . '/../Domain/data/transaction_valid.php', + include __DIR__ . '/../Domain/data/transaction_valid.php', + ], + 'pagination' => [ + 'total' => 2, + 'offset' => 0, + 'limit' => 2, + ], + ] + ); + Assert::string($responseBody); + + $sdk = MockedClientFactory::makeSdk( + 200, + $responseBody, + MockedClientFactory::assertRoute('GET', 'v2/billing/financialtransactions', $this) + ); + + $sdk->financial->listTransactions(2, 0, 'identifier:eq=something'); + } + + public function test_list_with_search_and_parameters(): void + { + $parameters = [ + 'processType' => 'incomingTransfer', + 'order' => '-updatedDate', + ]; + + /** @var string $responseBody */ + $responseBody = json_encode( + [ + 'entities' => [ + include __DIR__ . '/../Domain/data/transaction_valid.php', + include __DIR__ . '/../Domain/data/transaction_valid.php', + ], + 'pagination' => [ + 'total' => 2, + 'offset' => 0, + 'limit' => 2, + ], + ] + ); + + $sdk = MockedClientFactory::makeSdk( + 200, + $responseBody, + MockedClientFactory::assertRoute('GET', 'v2/billing/financialtransactions', $this, [ + 'processType' => 'incomingTransfer', + 'order' => '-updatedDate', + 'limit' => '2', + 'offset' => '0', + 'q' => 'search', + ]) + ); + + $sdk->financial->listTransactions(2, 0, 'search', $parameters); + } +} diff --git a/tests/Domain/data/exchangerates_valid.php b/tests/Domain/data/exchangerates_valid.php new file mode 100644 index 0000000..a2a58db --- /dev/null +++ b/tests/Domain/data/exchangerates_valid.php @@ -0,0 +1,8 @@ + 'EUR', + 'exchangerates' => [ + 'USD' => 1000000, + ], +]; diff --git a/tests/Domain/data/transaction_valid.php b/tests/Domain/data/transaction_valid.php new file mode 100644 index 0000000..78dfe67 --- /dev/null +++ b/tests/Domain/data/transaction_valid.php @@ -0,0 +1,20 @@ + 654563, + 'customer' => 'johndoe', + 'date' => '2021-08-11T06:17:15Z', + 'amount' => 1000000, + 'currency' => 'EUR', + 'processId' => 46069000, + 'processType' => 'contact', + 'processIdentifier' => 'rtr-handle123', + 'processAction' => 'update', + 'chargesPerAccount' => [ + 'USD' => 1000000, + ], + 'billables' => [ + include __DIR__ . '/billable_valid.php', + include __DIR__ . '/billable_valid.php', + ], +];