diff --git a/Tests/Feature/AffiliateSeller/IndexAffiliateSellersTest.php b/Tests/Feature/AffiliateSeller/IndexAffiliateSellersTest.php new file mode 100644 index 0000000..c8c6f90 --- /dev/null +++ b/Tests/Feature/AffiliateSeller/IndexAffiliateSellersTest.php @@ -0,0 +1,181 @@ +include($include)->get(); + + static::assertSame(1, $sellers[0]->id()); + static::assertSame("/v2/affiliates/sellers?include=$includeValue", $client->path()); + } + + /** + * Data provider for index_sellers_with_relations. + */ + public static function relationsProvider(): array + { + return [ + 'address' => [AffiliateSellerIncludes::ADDRESS, 'address'], + 'contact' => [AffiliateSellerIncludes::CONTACT, 'contact'], + 'profile' => [AffiliateSellerIncludes::PROFILE, 'profile'], + 'statistics' => [AffiliateSellerIncludes::STATISTICS, 'statistics'], + 'payoutOptions' => [AffiliateSellerIncludes::PAYOUT_OPTIONS, 'payout_options'], + 'payoutMethods' => [AffiliateSellerIncludes::PAYOUT_METHODS, 'payout_methods'], + ]; + } + + /** + * @dataProvider sellerFilterDataProvider + * @test + */ + public function index_sellers_with_filter(string $method, mixed $value, string $queryKey, string $queryValue): void + { + $client = (new AffiliateSellerIndexMockClient()); + $service = new AffiliateSellerService($client); + + $filter = (new AffiliateSellerFilter())->$method($value); + $service->get($filter); + + static::assertSame("/v2/affiliates/sellers?$queryKey=$queryValue", $client->path()); + } + + /** + * @test + */ + public function index_sellers_with_null_decline_reason(): void + { + $client = (new AffiliateSellerIndexMockClient([ + [ + 'id' => 1, + 'name' => 'John Doe', + 'email' => 'john@example.com', + 'decline_reason' => null, + 'profile_id' => 1, + 'status' => 'accepted', + 'payout_methods' => null, + ], + ])); + $service = new AffiliateSellerService($client); + $sellers = $service->get(); + + static::assertSame(1, $sellers[0]->id()); + static::assertNull($sellers[0]->declineReason()); + } + + /** + * Data provider for index_sellers_with_filter. + */ + public static function sellerFilterDataProvider(): array + { + return [ + [ + 'method' => 'limit', + 'value' => 10, + 'queryKey' => 'limit', + 'queryValue' => '10', + ], + [ + 'method' => 'sort', + 'value' => SellerSortType::NAME, + 'queryKey' => 'sort', + 'queryValue' => 'name', + ], + [ + 'method' => 'sort', + 'value' => SellerSortType::COMMISSION, + 'queryKey' => 'sort', + 'queryValue' => 'commission', + ], + [ + 'method' => 'sort', + 'value' => SellerSortType::LOCKED_REVENUE, + 'queryKey' => 'sort', + 'queryValue' => 'locked_revenue', + ], + [ + 'method' => 'sort', + 'value' => SellerSortType::PAID_REVENUE, + 'queryKey' => 'sort', + 'queryValue' => 'paid_revenue', + ], + [ + 'method' => 'sort', + 'value' => SellerSortType::PENDING_REVENUE, + 'queryKey' => 'sort', + 'queryValue' => 'pending_revenue', + ], + [ + 'method' => 'sort', + 'value' => SellerSortType::SALES, + 'queryKey' => 'sort', + 'queryValue' => 'sales', + ], + [ + 'method' => 'sort', + 'value' => SellerSortType::TOTAL_REVENUE, + 'queryKey' => 'sort', + 'queryValue' => 'total_revenue', + ], + [ + 'method' => 'direction', + 'value' => Direction::DESC, + 'queryKey' => 'direction', + 'queryValue' => 'desc', + ], + [ + 'method' => 'query', + 'value' => 'John', + 'queryKey' => 'q', + 'queryValue' => 'John', + ], + [ + 'method' => 'status', + 'value' => SellerStatus::ACCEPTED, + 'queryKey' => 'status', + 'queryValue' => 'accepted', + ], + [ + 'method' => 'eligibleForPayout', + 'value' => true, + 'queryKey' => 'eligible_for_payout', + 'queryValue' => '1', + ], + [ + 'method' => 'since', + 'value' => new DateTime('2023-01-01'), + 'queryKey' => 'since', + 'queryValue' => '2023-01-01', + ], + [ + 'method' => 'until', + 'value' => new DateTime('2023-12-31'), + 'queryKey' => 'until', + 'queryValue' => '2023-12-31', + ], + ]; + } +} diff --git a/Tests/Feature/AffiliateSeller/Mock/AffiliateSellerIndexMockClient.php b/Tests/Feature/AffiliateSeller/Mock/AffiliateSellerIndexMockClient.php new file mode 100644 index 0000000..2cc1fc8 --- /dev/null +++ b/Tests/Feature/AffiliateSeller/Mock/AffiliateSellerIndexMockClient.php @@ -0,0 +1,33 @@ +responseBody[] = $sellerData + AffiliateSellerShowMockClient::BASIC_SELLER; + } + } + + public function get(string $path): Response + { + $this->path = $path; + + return new Response(Response::HTTP_OK, ['data' => $this->responseBody]); + } + + public function path(): string + { + return $this->path; + } +} diff --git a/Tests/Feature/AffiliateSeller/Mock/AffiliateSellerShowMockClient.php b/Tests/Feature/AffiliateSeller/Mock/AffiliateSellerShowMockClient.php new file mode 100644 index 0000000..7b0330b --- /dev/null +++ b/Tests/Feature/AffiliateSeller/Mock/AffiliateSellerShowMockClient.php @@ -0,0 +1,149 @@ + 1, + 'name' => 'John Doe', + 'email' => 'john@example.com', + 'decline_reason' => '', + 'profile_id' => 1, + 'status' => 'accepted', + ]; + protected string $path; + + /** @noinspection PhpMissingParentConstructorInspection */ + public function __construct(array $data = []) + { + $this->responseBody = ['data' => $data + self::BASIC_SELLER]; + } + + public function address(array $data = []): self + { + $this->responseBody['data']['address'] = $data + [ + 'city' => 'New York', + 'country' => 'US', + 'street' => 'Main St', + 'housenumber' => '123', + 'zipcode' => '10001', + ]; + + return $this; + } + + public function contact(array $data = []): self + { + $this->responseBody['data']['contact'] = $data + [ + 'company' => 'ACME Corp', + 'email' => 'john@example.com', + 'firstname' => 'John', + 'lastname' => 'Doe', + 'telephone' => '+1234567890', + 'website' => 'https://example.com', + 'vat_id_number' => 'US123456789', + 'tax_exempt' => 'none', + ]; + + return $this; + } + + /** + * @throws NotFoundException + * @throws ValidationException + * @throws JsonException + */ + public function get(string $path): Response + { + $this->path = $path; + $response = new Response(Response::HTTP_OK, $this->responseBody); + + $exception = ExceptionFactory::create($response->status(), json_encode($response->body(), JSON_THROW_ON_ERROR)); + if ($exception) { + throw $exception; + } + + return $response; + } + + public function path(): string + { + return $this->path; + } + + public function profile(array $data = []): self + { + $this->responseBody['data']['profile'] = $data + [ + 'id' => 14, + 'default_recurring' => false, + 'default_type' => 'percentage', + 'default_value' => '50.00', + 'default_form_value' => '2.50', + 'label' => '', + 'session_lifetime' => 120, + 'tenant_id' => 3, + ]; + + return $this; + } + + public function statistics(array $data = []): self + { + $this->responseBody['data']['statistics'] = $data + [ + 'clicks' => null, + 'commission' => 0, + 'locked' => 0, + 'orders' => 0, + 'paidout' => 0, + 'pending' => 0, + 'recurring' => 0, + 'sales' => 0, + 'value' => 0, + ]; + + return $this; + } + + public function payoutOptions(array $data = []): self + { + $this->responseBody['data']['payout_options'] = $data + [ + 'method' => 'paypal', + 'settings' => [ + 'email' => 'oramcharan@example.com', + 'phone' => '+3177 4223366', + 'paypal_me_link' => 'https://paypal.me/lopes.jennifer', + ], + ]; + + return $this; + } + + public function payoutMethods(?array $data = null): self + { + if ($data === null) { + $data = [ + [ + 'method' => 'bank_transfer', + 'settings' => [ + 'iban' => 'NL91ABNA0417164300', + 'bic' => 'ABNANL2A', + ], + ], + ]; + } + + $this->responseBody['data']['payout_methods'] = $data; + + return $this; + } +} diff --git a/Tests/Feature/AffiliateSeller/ShowAffiliateSellerTest.php b/Tests/Feature/AffiliateSeller/ShowAffiliateSellerTest.php new file mode 100644 index 0000000..601b9a6 --- /dev/null +++ b/Tests/Feature/AffiliateSeller/ShowAffiliateSellerTest.php @@ -0,0 +1,502 @@ + 1]); + $service = new AffiliateSellerService($client); + + $seller = $service->find(1); + + static::assertSame(1, $seller->id()); + static::assertSame('John Doe', $seller->name()); + static::assertSame('john@example.com', $seller->email()); + static::assertSame('', $seller->declineReason()); + static::assertSame(1, $seller->profileId()); + static::assertSame(SellerStatus::ACCEPTED, $seller->status()); + static::assertSame('/v2/affiliates/sellers/1', $client->path()); + } + + /** + * @test + * @dataProvider relationsProvider + */ + public function show_none_loaded_relationships(string $relation): void + { + $exception = null; + + try { + (new AffiliateSeller(false))->{$relation}(); + } catch (RelationNotLoadedException $exception) { + } + + static::assertInstanceOf(RelationNotLoadedException::class, $exception); + } + + /** + * Data provider for show_none_loaded_relationships. + */ + public static function relationsProvider(): array + { + return [ + 'address' => ['address'], + 'contact' => ['contact'], + 'profile' => ['profile'], + 'statistics' => ['statistics'], + 'payoutOptions' => ['payoutOptions'], + 'payoutMethods' => ['payoutMethods'], + ]; + } + + /** @test */ + public function show_not_existing_seller(): void + { + $client = new ClientMock(Response::HTTP_NOT_FOUND); + $service = new AffiliateSellerService($client); + $exception = null; + + try { + $service->find(999); + } catch (NotFoundException $exception) { + } + + static::assertEquals('Not found', $exception->getMessage()); + } + + /** @test */ + public function show_unauthorized_seller(): void + { + $client = new ClientMock(Response::HTTP_UNAUTHORIZED); + $service = new AffiliateSellerService($client); + $exception = null; + + try { + $service->find(999); + } catch (UnauthenticatedException $exception) { + } + + static::assertEquals('Unable to connect with Plug&Pay. Request is unauthenticated.', $exception->getMessage()); + } + + /** @test */ + public function show_seller_with_address(): void + { + $client = (new AffiliateSellerShowMockClient())->address(); + $service = new AffiliateSellerService($client); + + $seller = $service->include(AffiliateSellerIncludes::ADDRESS)->find(1); + + $address = $seller->address(); + static::assertSame('New York', $address->city()); + static::assertSame(CountryCode::US, $address->country()); + static::assertSame('Main St', $address->street()); + static::assertSame('123', $address->houseNumber()); + static::assertSame('10001', $address->zipcode()); + static::assertSame('/v2/affiliates/sellers/1?include=address', $client->path()); + } + + /** @test */ + public function show_seller_with_contact(): void + { + $client = (new AffiliateSellerShowMockClient())->contact(); + $service = new AffiliateSellerService($client); + + $seller = $service->include(AffiliateSellerIncludes::CONTACT)->find(1); + + $contact = $seller->contact(); + static::assertSame('ACME Corp', $contact->company()); + static::assertSame('john@example.com', $contact->email()); + static::assertSame('John', $contact->firstName()); + static::assertSame('Doe', $contact->lastName()); + static::assertSame('+1234567890', $contact->telephone()); + static::assertSame('https://example.com', $contact->website()); + static::assertSame('/v2/affiliates/sellers/1?include=contact', $client->path()); + } + + /** @test */ + public function show_seller_with_profile(): void + { + $client = (new AffiliateSellerShowMockClient())->profile(); + $service = new AffiliateSellerService($client); + + $seller = $service->include(AffiliateSellerIncludes::PROFILE)->find(1); + + $profile = $seller->profile(); + static::assertSame(14, $profile->id()); + static::assertSame('/v2/affiliates/sellers/1?include=profile', $client->path()); + } + + /** @test */ + public function show_seller_with_statistics(): void + { + $client = (new AffiliateSellerShowMockClient())->statistics(); + $service = new AffiliateSellerService($client); + + $seller = $service->include(AffiliateSellerIncludes::STATISTICS)->find(1); + + $statistics = $seller->statistics(); + static::assertInstanceOf(SellerStatistics::class, $statistics); + static::assertSame('/v2/affiliates/sellers/1?include=statistics', $client->path()); + } + + /** @test */ + public function show_seller_with_payout_options(): void + { + $client = (new AffiliateSellerShowMockClient())->payoutOptions(); + $service = new AffiliateSellerService($client); + + $seller = $service->include(AffiliateSellerIncludes::PAYOUT_OPTIONS)->find(1); + + $payoutOptions = $seller->payoutOptions(); + static::assertInstanceOf(SellerPayoutOptions::class, $payoutOptions); + static::assertSame('/v2/affiliates/sellers/1?include=payout_options', $client->path()); + } + + /** @test */ + public function show_seller_statistics_with_values(): void + { + $client = (new AffiliateSellerShowMockClient())->statistics([ + 'clicks' => 150, + 'commission' => 2500, + 'locked' => 750, + 'orders' => 42, + 'paidout' => 10000, + 'pending' => 1250, + 'recurring' => 3500, + 'sales' => 55, + 'value' => 15000, + ]); + $service = new AffiliateSellerService($client); + + $seller = $service->include(AffiliateSellerIncludes::STATISTICS)->find(1); + + $statistics = $seller->statistics(); + static::assertSame(150, $statistics->clicks()); + static::assertSame(2500.0, $statistics->commission()); + static::assertSame(750.0, $statistics->locked()); + static::assertSame(42, $statistics->orders()); + static::assertSame(10000.0, $statistics->paidout()); + static::assertSame(1250.0, $statistics->pending()); + static::assertSame(3500.0, $statistics->recurring()); + static::assertSame(55, $statistics->sales()); + static::assertSame(15000.0, $statistics->value()); + } + + /** @test */ + public function show_seller_statistics_with_null_clicks(): void + { + $client = (new AffiliateSellerShowMockClient())->statistics([ + 'clicks' => null, + ]); + $service = new AffiliateSellerService($client); + + $seller = $service->include(AffiliateSellerIncludes::STATISTICS)->find(1); + + $statistics = $seller->statistics(); + static::assertNull($statistics->clicks()); + } + + /** @test */ + public function show_seller_profile_with_custom_id(): void + { + $client = (new AffiliateSellerShowMockClient())->profile([ + 'id' => 42, + ]); + $service = new AffiliateSellerService($client); + + $seller = $service->include(AffiliateSellerIncludes::PROFILE)->find(1); + + $profile = $seller->profile(); + static::assertSame(42, $profile->id()); + } + + /** @test */ + public function show_seller_profile_with_values(): void + { + $client = (new AffiliateSellerShowMockClient())->profile([ + 'id' => 99, + 'default_recurring' => 1, + 'default_type' => 'fixed', + 'default_value' => '100.00', + 'default_form_value' => '5.00', + 'label' => 'Premium Seller', + 'session_lifetime' => 300, + 'tenant_id' => 7, + ]); + $service = new AffiliateSellerService($client); + + $seller = $service->include(AffiliateSellerIncludes::PROFILE)->find(1); + + $profile = $seller->profile(); + static::assertSame(99, $profile->id()); + static::assertTrue($profile->defaultRecurring()); + static::assertSame('fixed', $profile->defaultType()); + static::assertSame(100.0, $profile->defaultValue()); + static::assertSame(5.0, $profile->defaultFormValue()); + static::assertSame('Premium Seller', $profile->label()); + static::assertSame(300, $profile->sessionLifetime()); + static::assertSame(7, $profile->tenantId()); + } + + /** @test */ + public function show_seller_profile_with_recurring_enabled(): void + { + $client = (new AffiliateSellerShowMockClient())->profile([ + 'default_recurring' => true, + ]); + $service = new AffiliateSellerService($client); + + $seller = $service->include(AffiliateSellerIncludes::PROFILE)->find(1); + + $profile = $seller->profile(); + static::assertTrue($profile->defaultRecurring()); + } + + /** @test */ + public function show_seller_profile_with_zero_values(): void + { + $client = (new AffiliateSellerShowMockClient())->profile([ + 'default_value' => '0.00', + 'default_form_value' => '0.00', + 'session_lifetime' => 0, + ]); + $service = new AffiliateSellerService($client); + + $seller = $service->include(AffiliateSellerIncludes::PROFILE)->find(1); + + $profile = $seller->profile(); + static::assertSame(0.0, $profile->defaultValue()); + static::assertSame(0.0, $profile->defaultFormValue()); + static::assertSame(0, $profile->sessionLifetime()); + } + + /** @test */ + public function test_seller_statistics_isset_for_existing_property(): void + { + $client = (new AffiliateSellerShowMockClient())->statistics([ + 'clicks' => 100, + 'commission' => 500, + 'locked' => 200, + 'orders' => 10, + 'paidout' => 1000, + 'pending' => 300, + 'recurring' => 400, + 'sales' => 15, + 'value' => 2000, + ]); + $service = new AffiliateSellerService($client); + + $seller = $service->include(AffiliateSellerIncludes::STATISTICS)->find(1); + + $statistics = $seller->statistics(); + static::assertTrue($statistics->isset('clicks')); + static::assertTrue($statistics->isset('commission')); + static::assertTrue($statistics->isset('locked')); + static::assertTrue($statistics->isset('orders')); + static::assertTrue($statistics->isset('paidout')); + static::assertTrue($statistics->isset('pending')); + static::assertTrue($statistics->isset('recurring')); + static::assertTrue($statistics->isset('sales')); + static::assertTrue($statistics->isset('value')); + } + + /** @test */ + public function test_seller_payout_options_isset(): void + { + $client = (new AffiliateSellerShowMockClient())->payoutOptions(); + $service = new AffiliateSellerService($client); + + $seller = $service->include(AffiliateSellerIncludes::PAYOUT_OPTIONS)->find(1); + + $payoutOptions = $seller->payoutOptions(); + static::assertInstanceOf(SellerPayoutOptions::class, $payoutOptions); + } + + /** @test */ + public function show_seller_payout_options_with_default_data(): void + { + $client = (new AffiliateSellerShowMockClient())->payoutOptions(); + $service = new AffiliateSellerService($client); + + $seller = $service->include(AffiliateSellerIncludes::PAYOUT_OPTIONS)->find(1); + + $payoutOptions = $seller->payoutOptions(); + static::assertSame('paypal', $payoutOptions->method()); + + $settings = $payoutOptions->settings(); + static::assertIsArray($settings); + static::assertSame('oramcharan@example.com', $settings['email']); + static::assertSame('+3177 4223366', $settings['phone']); + static::assertSame('https://paypal.me/lopes.jennifer', $settings['paypal_me_link']); + } + + /** @test */ + public function show_seller_payout_options_with_custom_method(): void + { + $client = (new AffiliateSellerShowMockClient())->payoutOptions([ + 'method' => 'bank_transfer', + ]); + $service = new AffiliateSellerService($client); + + $seller = $service->include(AffiliateSellerIncludes::PAYOUT_OPTIONS)->find(1); + + $payoutOptions = $seller->payoutOptions(); + static::assertSame('bank_transfer', $payoutOptions->method()); + } + + /** @test */ + public function show_seller_payout_options_with_custom_settings(): void + { + $client = (new AffiliateSellerShowMockClient())->payoutOptions([ + 'method' => 'paypal', + 'settings' => [ + 'email' => 'custom@example.com', + 'phone' => '+31612345678', + 'paypal_me_link' => 'https://paypal.me/custom.user', + ], + ]); + $service = new AffiliateSellerService($client); + + $seller = $service->include(AffiliateSellerIncludes::PAYOUT_OPTIONS)->find(1); + + $payoutOptions = $seller->payoutOptions(); + $settings = $payoutOptions->settings(); + static::assertSame('custom@example.com', $settings['email']); + static::assertSame('+31612345678', $settings['phone']); + static::assertSame('https://paypal.me/custom.user', $settings['paypal_me_link']); + } + + /** @test */ + public function show_seller_payout_options_settings_fields(): void + { + $client = (new AffiliateSellerShowMockClient())->payoutOptions(); + $service = new AffiliateSellerService($client); + + $seller = $service->include(AffiliateSellerIncludes::PAYOUT_OPTIONS)->find(1); + + $payoutOptions = $seller->payoutOptions(); + static::assertTrue($payoutOptions->isset('method')); + static::assertTrue($payoutOptions->isset('settings')); + } + + /** @test */ + public function test_isset_with_non_existent_field_throws_exception(): void + { + $client = (new AffiliateSellerShowMockClient())->statistics(); + $service = new AffiliateSellerService($client); + + $seller = $service->include(AffiliateSellerIncludes::STATISTICS)->find(1); + + $this->expectException(BadFunctionCallException::class); + $this->expectExceptionMessage("Field 'nonExistentField' does not exists"); + $statistics = $seller->statistics(); + $statistics->isset('nonExistentField'); + } + + /** @test */ + public function show_seller_with_payout_methods(): void + { + $client = (new AffiliateSellerShowMockClient())->payoutMethods(); + $service = new AffiliateSellerService($client); + + $seller = $service->include(AffiliateSellerIncludes::PAYOUT_METHODS)->find(1); + + $payoutMethods = $seller->payoutMethods(); + static::assertIsArray($payoutMethods); + static::assertCount(1, $payoutMethods); + static::assertSame('bank_transfer', $payoutMethods[0]->method()); + static::assertIsArray($payoutMethods[0]->settings()); + static::assertSame('NL91ABNA0417164300', $payoutMethods[0]->settings()['iban']); + static::assertSame('ABNANL2A', $payoutMethods[0]->settings()['bic']); + static::assertSame('/v2/affiliates/sellers/1?include=payout_methods', $client->path()); + } + + /** @test */ + public function show_seller_payout_methods_with_bank_transfer(): void + { + $client = (new AffiliateSellerShowMockClient())->payoutMethods([ + [ + 'method' => 'bank_transfer', + 'settings' => [ + 'iban' => 'DE89370400440532013000', + 'bic' => 'COBADEFFXXX', + ], + ], + ]); + $service = new AffiliateSellerService($client); + + $seller = $service->find(1); + + $payoutMethods = $seller->payoutMethods(); + static::assertCount(1, $payoutMethods); + static::assertSame('bank_transfer', $payoutMethods[0]->method()); + static::assertSame('DE89370400440532013000', $payoutMethods[0]->settings()['iban']); + static::assertSame('COBADEFFXXX', $payoutMethods[0]->settings()['bic']); + } + + /** @test */ + public function show_seller_payout_methods_empty_array(): void + { + $client = (new AffiliateSellerShowMockClient())->payoutMethods([]); + $service = new AffiliateSellerService($client); + + $seller = $service->find(1); + + $payoutMethods = $seller->payoutMethods(); + static::assertIsArray($payoutMethods); + static::assertCount(0, $payoutMethods); + } + + /** @test */ + public function show_seller_payout_methods_multiple(): void + { + $client = (new AffiliateSellerShowMockClient())->payoutMethods([ + [ + 'method' => 'bank_transfer', + 'settings' => [ + 'iban' => 'NL91ABNA0417164300', + 'bic' => 'ABNANL2A', + ], + ], + [ + 'method' => 'paypal', + 'settings' => [ + 'email' => 'seller@example.com', + ], + ], + ]); + $service = new AffiliateSellerService($client); + + $seller = $service->find(1); + + $payoutMethods = $seller->payoutMethods(); + static::assertCount(2, $payoutMethods); + + static::assertSame('bank_transfer', $payoutMethods[0]->method()); + static::assertSame('paypal', $payoutMethods[1]->method()); + } +} diff --git a/src/Director/BodyTo/BodyToAffiliateSeller.php b/src/Director/BodyTo/BodyToAffiliateSeller.php new file mode 100644 index 0000000..aad1f1e --- /dev/null +++ b/src/Director/BodyTo/BodyToAffiliateSeller.php @@ -0,0 +1,55 @@ +setId($data['id']) + ->setName($data['name']) + ->setEmail($data['email']) + ->setDeclineReason($data['decline_reason'] ?? null) + ->setProfileId($data['profile_id']) + ->setStatus(SellerStatus::from($data['status'])); + + if (isset($data['address'])) { + $seller->setAddress(BodyToAddress::build($data['address'])); + } + + if (isset($data['contact'])) { + $seller->setContact(BodyToContact::build($data['contact'])); + } + + if (isset($data['profile'])) { + $seller->setProfile(BodyToSellerProfile::build($data['profile'])); + } + + if (isset($data['statistics'])) { + $seller->setStatistics(BodyToSellerStatistics::build($data['statistics'])); + } + + if (isset($data['payout_options'])) { + $seller->setPayoutOptions(BodyToSellerPayoutOptions::build($data['payout_options'])); + } + + if (isset($data['payout_methods'])) { + /* @noinspection PhpParamsInspection */ + $seller->setPayoutMethods(BodyToPayoutMethod::buildMulti($data['payout_methods'])); + } + + return $seller; + } +} diff --git a/src/Director/BodyTo/BodyToPayoutMethod.php b/src/Director/BodyTo/BodyToPayoutMethod.php new file mode 100644 index 0000000..677db09 --- /dev/null +++ b/src/Director/BodyTo/BodyToPayoutMethod.php @@ -0,0 +1,23 @@ +setMethod($data['method']) + ->setSettings($data['settings'] ?? null); + } +} diff --git a/src/Director/BodyTo/BodyToSellerPayoutOptions.php b/src/Director/BodyTo/BodyToSellerPayoutOptions.php new file mode 100644 index 0000000..281a384 --- /dev/null +++ b/src/Director/BodyTo/BodyToSellerPayoutOptions.php @@ -0,0 +1,19 @@ +setMethod($data['method'] ?? null) + ->setSettings($data['settings'] ?? null); + } +} diff --git a/src/Director/BodyTo/BodyToSellerProfile.php b/src/Director/BodyTo/BodyToSellerProfile.php new file mode 100644 index 0000000..b4b21ea --- /dev/null +++ b/src/Director/BodyTo/BodyToSellerProfile.php @@ -0,0 +1,25 @@ +setId($data['id']) + ->setDefaultRecurring((bool) $data['default_recurring']) + ->setDefaultType($data['default_type']) + ->setDefaultValue((float) $data['default_value']) + ->setDefaultFormValue((float) $data['default_form_value']) + ->setLabel($data['label']) + ->setSessionLifetime($data['session_lifetime']) + ->setTenantId($data['tenant_id']); + } +} diff --git a/src/Director/BodyTo/BodyToSellerStatistics.php b/src/Director/BodyTo/BodyToSellerStatistics.php new file mode 100644 index 0000000..1b88f7e --- /dev/null +++ b/src/Director/BodyTo/BodyToSellerStatistics.php @@ -0,0 +1,26 @@ +setClicks($data['clicks'] ?? null) + ->setCommission((float) ($data['commission'] ?? 0)) + ->setLocked((float) ($data['locked'] ?? 0)) + ->setOrders($data['orders'] ?? 0) + ->setPaidout((float) ($data['paidout'] ?? 0)) + ->setPending((float) ($data['pending'] ?? 0)) + ->setRecurring((float) $data['recurring'] ?? 0) + ->setSales($data['sales'] ?? 0) + ->setValue((float) ($data['value'] ?? 0)); + } +} diff --git a/src/Entity/AffiliateSeller.php b/src/Entity/AffiliateSeller.php new file mode 100644 index 0000000..633ce59 --- /dev/null +++ b/src/Entity/AffiliateSeller.php @@ -0,0 +1,196 @@ +allowEmptyRelations = $allowEmptyRelations; + } + + /** + * @throws RelationNotLoadedException + */ + public function address(): Address + { + if (!isset($this->address)) { + if ($this->allowEmptyRelations) { + $this->address = new Address(); + } else { + throw new RelationNotLoadedException('address'); + } + } + + return $this->address; + } + + public function setAddress(Address $address): self + { + $this->address = $address; + + return $this; + } + + /** + * @throws RelationNotLoadedException + */ + public function contact(): Contact + { + if (!isset($this->contact)) { + if ($this->allowEmptyRelations) { + $this->contact = new Contact(); + } else { + throw new RelationNotLoadedException('contact'); + } + } + + return $this->contact; + } + + public function setContact(Contact $contact): self + { + $this->contact = $contact; + + return $this; + } + + public function declineReason(): ?string + { + return $this->declineReason; + } + + public function email(): string + { + return $this->email; + } + + public function id(): int + { + return $this->id; + } + + public function name(): string + { + return $this->name; + } + + /** + * @throws RelationNotLoadedException + */ + public function profile(): SellerProfile + { + if (!isset($this->profile)) { + if ($this->allowEmptyRelations) { + $this->profile = new SellerProfile(); + } else { + throw new RelationNotLoadedException('profile'); + } + } + + return $this->profile; + } + + public function setProfile(SellerProfile $profile): self + { + $this->profile = $profile; + + return $this; + } + + public function profileId(): int + { + return $this->profileId; + } + + /** + * @throws RelationNotLoadedException + */ + public function statistics(): SellerStatistics + { + if (!isset($this->statistics)) { + if ($this->allowEmptyRelations) { + $this->statistics = new SellerStatistics(); + } else { + throw new RelationNotLoadedException('statistics'); + } + } + + return $this->statistics; + } + + public function setStatistics(SellerStatistics $statistics): self + { + $this->statistics = $statistics; + + return $this; + } + + public function status(): SellerStatus + { + return $this->status; + } + + /** + * @throws RelationNotLoadedException + */ + public function payoutOptions(): SellerPayoutOptions + { + if (!isset($this->payoutOptions)) { + if ($this->allowEmptyRelations) { + $this->payoutOptions = new SellerPayoutOptions(); + } else { + throw new RelationNotLoadedException('payoutOptions'); + } + } + + return $this->payoutOptions; + } + + public function setPayoutOptions(SellerPayoutOptions $payoutOptions): self + { + $this->payoutOptions = $payoutOptions; + + return $this; + } + + /** + * @throws RelationNotLoadedException + * @return PayoutMethod[] + */ + public function payoutMethods(): array + { + if (!isset($this->payoutMethods)) { + if ($this->allowEmptyRelations) { + $this->payoutMethods = []; + } else { + throw new RelationNotLoadedException('payoutMethods'); + } + } + + return $this->payoutMethods; + } +} diff --git a/src/Entity/AffiliateSellerInternal.php b/src/Entity/AffiliateSellerInternal.php new file mode 100644 index 0000000..fa38b97 --- /dev/null +++ b/src/Entity/AffiliateSellerInternal.php @@ -0,0 +1,63 @@ +declineReason = $declineReason; + + return $this; + } + + public function setEmail(string $email): self + { + $this->email = $email; + + return $this; + } + + public function setId(int $id): self + { + $this->id = $id; + + return $this; + } + + public function setName(string $name): self + { + $this->name = $name; + + return $this; + } + + public function setProfileId(int $profileId): self + { + $this->profileId = $profileId; + + return $this; + } + + public function setStatus(SellerStatus $status): self + { + $this->status = $status; + + return $this; + } + + /** + * @param PayoutMethod[] $payoutMethods + * @return $this + */ + public function setPayoutMethods(array $payoutMethods): self + { + $this->payoutMethods = $payoutMethods; + + return $this; + } +} diff --git a/src/Entity/PayoutMethod.php b/src/Entity/PayoutMethod.php new file mode 100644 index 0000000..9ce1495 --- /dev/null +++ b/src/Entity/PayoutMethod.php @@ -0,0 +1,21 @@ +method; + } + + public function settings(): ?array + { + return $this->settings; + } +} diff --git a/src/Entity/PayoutMethodInternal.php b/src/Entity/PayoutMethodInternal.php new file mode 100644 index 0000000..edc12c6 --- /dev/null +++ b/src/Entity/PayoutMethodInternal.php @@ -0,0 +1,25 @@ +method = $method; + + return $this; + } + + public function setSettings(?array $settings): self + { + $this->settings = $settings; + + return $this; + } +} diff --git a/src/Entity/SellerPayoutOptions.php b/src/Entity/SellerPayoutOptions.php new file mode 100644 index 0000000..9ffce21 --- /dev/null +++ b/src/Entity/SellerPayoutOptions.php @@ -0,0 +1,39 @@ +method; + } + + public function setMethod(?string $method): self + { + $this->method = $method; + + return $this; + } + + public function settings(): ?array + { + return $this->settings; + } + + public function setSettings(?array $settings): self + { + $this->settings = $settings; + + return $this; + } +} diff --git a/src/Entity/SellerPayoutOptionsInternal.php b/src/Entity/SellerPayoutOptionsInternal.php new file mode 100644 index 0000000..ea180c3 --- /dev/null +++ b/src/Entity/SellerPayoutOptionsInternal.php @@ -0,0 +1,10 @@ +id; + } + + public function defaultRecurring(): bool + { + return $this->defaultRecurring; + } + + public function defaultType(): string + { + return $this->defaultType; + } + + public function defaultValue(): float + { + return $this->defaultValue; + } + + public function defaultFormValue(): float + { + return $this->defaultFormValue; + } + + public function label(): string + { + return $this->label; + } + + public function sessionLifetime(): int + { + return $this->sessionLifetime; + } + + public function tenantId(): int + { + return $this->tenantId; + } +} diff --git a/src/Entity/SellerProfileInternal.php b/src/Entity/SellerProfileInternal.php new file mode 100644 index 0000000..147428b --- /dev/null +++ b/src/Entity/SellerProfileInternal.php @@ -0,0 +1,64 @@ +id = $id; + + return $this; + } + + public function setDefaultRecurring(bool $defaultRecurring): self + { + $this->defaultRecurring = $defaultRecurring; + + return $this; + } + + public function setDefaultType(string $defaultType): self + { + $this->defaultType = $defaultType; + + return $this; + } + + public function setDefaultValue(float $defaultValue): self + { + $this->defaultValue = $defaultValue; + + return $this; + } + + public function setDefaultFormValue(float $defaultFormValue): self + { + $this->defaultFormValue = $defaultFormValue; + + return $this; + } + + public function setLabel(string $label): self + { + $this->label = $label; + + return $this; + } + + public function setSessionLifetime(int $sessionLifetime): self + { + $this->sessionLifetime = $sessionLifetime; + + return $this; + } + + public function setTenantId(int $tenantId): self + { + $this->tenantId = $tenantId; + + return $this; + } +} diff --git a/src/Entity/SellerStatistics.php b/src/Entity/SellerStatistics.php new file mode 100644 index 0000000..e48515f --- /dev/null +++ b/src/Entity/SellerStatistics.php @@ -0,0 +1,67 @@ +clicks; + } + + public function commission(): float + { + return $this->commission; + } + + public function locked(): float + { + return $this->locked; + } + + public function orders(): int + { + return $this->orders; + } + + public function paidout(): float + { + return $this->paidout; + } + + public function pending(): float + { + return $this->pending; + } + + public function recurring(): float + { + return $this->recurring; + } + + public function sales(): int + { + return $this->sales; + } + + public function value(): float + { + return $this->value; + } +} diff --git a/src/Entity/SellerStatisticsInternal.php b/src/Entity/SellerStatisticsInternal.php new file mode 100644 index 0000000..1b7a5a3 --- /dev/null +++ b/src/Entity/SellerStatisticsInternal.php @@ -0,0 +1,74 @@ +clicks = $clicks; + + return $this; + } + + public function setCommission(float $commission): self + { + $this->commission = $commission; + + return $this; + } + + public function setLocked(float $locked): self + { + $this->locked = $locked; + + return $this; + } + + public function setOrders(int $orders): self + { + $this->orders = $orders; + + return $this; + } + + public function setPaidout(float $paidout): self + { + $this->paidout = $paidout; + + return $this; + } + + public function setPending(float $pending): self + { + $this->pending = $pending; + + return $this; + } + + public function setRecurring(float $recurring): self + { + $this->recurring = $recurring; + + return $this; + } + + public function setSales(int $sales): self + { + $this->sales = $sales; + + return $this; + } + + public function setValue(float $value): self + { + $this->value = $value; + + return $this; + } +} diff --git a/src/Enum/AffiliateSellerIncludes.php b/src/Enum/AffiliateSellerIncludes.php new file mode 100644 index 0000000..195d67b --- /dev/null +++ b/src/Enum/AffiliateSellerIncludes.php @@ -0,0 +1,15 @@ +parameters['direction'] = $direction->value; + + return $this; + } + + public function eligibleForPayout(bool $value): self + { + $this->parameters['eligible_for_payout'] = $value; + + return $this; + } + + public function limit(int $value): self + { + $this->parameters['limit'] = $value; + + return $this; + } + + public function parameters(): array + { + return $this->parameters; + } + + public function query(string $value): self + { + $this->parameters['q'] = $value; + + return $this; + } + + public function since(DateTimeInterface $value): self + { + $this->parameters['since'] = $value->format('Y-m-d'); + + return $this; + } + + public function sort(SellerSortType $value): self + { + $this->parameters['sort'] = $value->value; + + return $this; + } + + public function status(SellerStatus ...$status): self + { + $this->parameters['status'] = $status; + + return $this; + } + + public function until(DateTimeInterface $value): self + { + $this->parameters['until'] = $value->format('Y-m-d'); + + return $this; + } +} diff --git a/src/Service/AffiliateSellerService.php b/src/Service/AffiliateSellerService.php new file mode 100644 index 0000000..b4059ab --- /dev/null +++ b/src/Service/AffiliateSellerService.php @@ -0,0 +1,61 @@ +client = $client; + } + + public function include(AffiliateSellerIncludes ...$includes): self + { + $this->includes = $includes; + + return $this; + } + + /** + * @throws DecodeResponseException + */ + public function find(int $id): AffiliateSeller + { + $query = Parameters::toString(['include' => $this->includes]); + $response = $this->client->get("/v2/affiliates/sellers/$id$query"); + + return BodyToAffiliateSeller::build($response->body()['data']); + } + + /** + * @return AffiliateSeller[] + * @throws DecodeResponseException + */ + public function get(?AffiliateSellerFilter $filter = null): array + { + $parameters = $filter ? $filter->parameters() : []; + if (!empty($this->includes)) { + $parameters['include'] = $this->includes; + } + $query = Parameters::toString($parameters); + + $response = $this->client->get("/v2/affiliates/sellers$query"); + + return BodyToAffiliateSeller::buildMulti($response->body()['data']); + } +}