From 8c445f6525ab495022b0d7c5b84a309e568e9007 Mon Sep 17 00:00:00 2001 From: Lukasz Falda Date: Fri, 27 Jun 2025 11:33:33 +0200 Subject: [PATCH] Apms by region request --- README.md | 17 ++- grumphp.yaml | 3 + src/ConfigProvider.php | 2 +- src/DTO/PickupPointDTO.php | 1 + src/Enum/RegionEnum.php | 12 ++ .../GetPickupPointsByRegionRequest.php | 38 ++++++ src/Response/GetPickupPointsAmpsResponse.php | 1 + src/Response/GetPickupPointsResponse.php | 3 +- src/Service/PickupPointService.php | 16 +++ .../PickupPointByRegionServiceTest.php | 108 +++++++++++++++ .../assert-valid-data-by-region.json | 114 ++++++++++++++++ .../data/pickup-points/success-by-region.json | 123 ++++++++++++++++++ 12 files changed, 433 insertions(+), 5 deletions(-) create mode 100644 src/Enum/RegionEnum.php create mode 100644 src/Request/GetPickupPointsByRegionRequest.php create mode 100644 tests/Integration/Service/PickupPointByRegionServiceTest.php create mode 100644 tests/data/pickup-points/assert-valid-data-by-region.json create mode 100644 tests/data/pickup-points/success-by-region.json diff --git a/README.md b/README.md index cf13a4caf5..5e05f3b6d9 100644 --- a/README.md +++ b/README.md @@ -23,15 +23,16 @@ should be added automatically to your `config/bundles.php` file by Symfony Flex. answear_box_now: clientId: yourClientId clientSecret: yourClientSecret - apiUrl: apiUrl #default: 'https://api-stage.boxnow.gr' + apiUrl: apiUrl #default: 'https://locationapi-stage.boxnow.gr' logger: customLogger #default: null ``` -Logger service must implement Psr\Log\LoggerInterface interface. +Logger service must implement Psr\Log\LoggerInterface interface. ## Usage ### Authorization + ```php /** @var \Answear\BoxNowBundle\Service\AuthorizationService $authorizationService **/ $auth = $authorizationService->authorize(); @@ -40,16 +41,26 @@ $auth->getAccessToken(); $auth->getExpiresIn(); $auth->getTokenType(); ``` -will return `\Answear\BoxNowBundle\Response\AuthorizationResponse`. +will return `\Answear\BoxNowBundle\Response\AuthorizationResponse`. ### Pickup points + ```php /** @var \Answear\BoxNowBundle\Service\PickupPointService $pickupPoints **/ $pickupPoints->getAll(token: 'accessToken'); ``` + will return `\Answear\BoxNowBundle\DTO\PickupPointDTO[]`. +Or with locationapi (ex. https://locationapi-stage.boxnow.gr/v1/apms_el-GR.json) +```php +/** @var \Answear\BoxNowBundle\Service\PickupPointService $pickupPoints **/ +$pickupPoints->getAllByRegion(\Answear\BoxNowBundle\Enum\RegionEnum::Cyprus); +``` + +will return `\Answear\BoxNowBundle\DTO\PickupPointDTO[]` only for Cyprus (available Greece, Cyprus, Croatia). + Final notes ------------ diff --git a/grumphp.yaml b/grumphp.yaml index 3808677cfc..26dbfe2724 100755 --- a/grumphp.yaml +++ b/grumphp.yaml @@ -1,5 +1,8 @@ grumphp: process_timeout: 120 + environment: + variables: + PHP_CS_FIXER_IGNORE_ENV: "1" ascii: failed: ~ succeeded: ~ diff --git a/src/ConfigProvider.php b/src/ConfigProvider.php index 38983eff1a..b72856b5ab 100644 --- a/src/ConfigProvider.php +++ b/src/ConfigProvider.php @@ -6,7 +6,7 @@ class ConfigProvider { - private const API_URL = 'https://api-stage.boxnow.gr'; + private const API_URL = 'https://locationapi-stage.boxnow.gr'; public function __construct( public readonly string $clientId, diff --git a/src/DTO/PickupPointDTO.php b/src/DTO/PickupPointDTO.php index b0529d4298..6937aed517 100644 --- a/src/DTO/PickupPointDTO.php +++ b/src/DTO/PickupPointDTO.php @@ -7,6 +7,7 @@ public function __construct( public string $id, public string $type, + public string $state, public string $name, public string $address, public ?string $title = null, diff --git a/src/Enum/RegionEnum.php b/src/Enum/RegionEnum.php new file mode 100644 index 0000000000..7fb43ff48f --- /dev/null +++ b/src/Enum/RegionEnum.php @@ -0,0 +1,12 @@ +region->value, self::ENDPOINT); + } + + public function getMethod(): string + { + return self::HTTP_METHOD; + } + + public function getUrlQuery(): ?string + { + return null; + } + + public function getHeaders(): array + { + return []; + } +} diff --git a/src/Response/GetPickupPointsAmpsResponse.php b/src/Response/GetPickupPointsAmpsResponse.php index 2c1053ef0b..38237b0261 100644 --- a/src/Response/GetPickupPointsAmpsResponse.php +++ b/src/Response/GetPickupPointsAmpsResponse.php @@ -25,6 +25,7 @@ public function handleData(array $data): void $this->pickupPoints[] = new PickupPointDTO( $pickupPoint['id'], $pickupPoint['state'], + $pickupPoint['state'], $pickupPoint['name'], $pickupPoint['addressLine1'], $pickupPoint['title'] ?? null, diff --git a/src/Response/GetPickupPointsResponse.php b/src/Response/GetPickupPointsResponse.php index e7bae28a2e..461873b9dc 100644 --- a/src/Response/GetPickupPointsResponse.php +++ b/src/Response/GetPickupPointsResponse.php @@ -25,7 +25,8 @@ public function handleData(array $data): void $this->pickupPoints[] = new PickupPointDTO( $pickupPoint['id'], $pickupPoint['type'], - $pickupPoint['name'], + $pickupPoint['state'] ?? '', + trim($pickupPoint['name']), $pickupPoint['addressLine1'], $pickupPoint['title'] ?? null, $pickupPoint['image'] ?? null, diff --git a/src/Service/PickupPointService.php b/src/Service/PickupPointService.php index 933794739d..292f95727d 100644 --- a/src/Service/PickupPointService.php +++ b/src/Service/PickupPointService.php @@ -4,7 +4,9 @@ use Answear\BoxNowBundle\Client\Client; use Answear\BoxNowBundle\DTO\PickupPointDTO; +use Answear\BoxNowBundle\Enum\RegionEnum; use Answear\BoxNowBundle\Request\GetPickupPointsAmpsRequest; +use Answear\BoxNowBundle\Request\GetPickupPointsByRegionRequest; use Answear\BoxNowBundle\Request\GetPickupPointsRequest; use Answear\BoxNowBundle\Response\GetPickupPointsAmpsResponse; use Answear\BoxNowBundle\Response\GetPickupPointsResponse; @@ -45,4 +47,18 @@ public function getAllWithRegion(string $token, string $region): array return $pickupPointsResponse->getPickupPoints(); } + + /** + * @return PickupPointDTO[] + */ + public function getAllByRegion(RegionEnum $region): array + { + $response = $this->client->request(new GetPickupPointsByRegionRequest($region)); + + $pickupPointsResponse = GetPickupPointsResponse::fromArray( + $this->serializer->decodeResponse($response) + ); + + return $pickupPointsResponse->getPickupPoints(); + } } diff --git a/tests/Integration/Service/PickupPointByRegionServiceTest.php b/tests/Integration/Service/PickupPointByRegionServiceTest.php new file mode 100644 index 0000000000..9939e5c7ef --- /dev/null +++ b/tests/Integration/Service/PickupPointByRegionServiceTest.php @@ -0,0 +1,108 @@ +setClient(withLogger: true); + $service = $this->getService(); + + $this->mockGuzzleResponse( + new Response( + status: SymfonyResponse::HTTP_OK, + body: FileTestUtil::getFileContents(__DIR__ . '/../../data/pickup-points/success-by-region.json') + ) + ); + + $pickupPoints = $service->getAllByRegion(RegionEnum::Croatia); + $actualData = []; + + foreach ($pickupPoints as $pickupPoint) { + $actualData[] = [ + 'id' => $pickupPoint->id, + 'type' => $pickupPoint->type, + 'name' => $pickupPoint->name, + 'address' => $pickupPoint->address, + 'title' => $pickupPoint->title, + 'image' => $pickupPoint->image, + 'latitude' => $pickupPoint->latitude, + 'longitude' => $pickupPoint->longitude, + 'postalCode' => $pickupPoint->postalCode, + 'country' => $pickupPoint->country, + 'note' => $pickupPoint->note, + 'additionalAddress' => $pickupPoint->additionalAddress, + 'expectedDeliveryTime' => $pickupPoint->expectedDeliveryTime, + 'region' => $pickupPoint->region, + ]; + + self::assertSame( + $pickupPoint->address . ', ' . $pickupPoint->additionalAddress, + $pickupPoint->getFullAddress(', ') + ); + } + + $this->assertJsonStringEqualsJsonString( + json_encode($actualData, JSON_THROW_ON_ERROR), + FileTestUtil::getFileContents(__DIR__ . '/../../data/pickup-points/assert-valid-data-by-region.json'), + ); + } + + #[Test] + public function invalidPickupPointIdFieldValue(): void + { + $this->expectException(InvalidArgumentException::class); + $this->expectExceptionMessage('Field id expected to be a string. Got: '); + + $this->setClient(); + $service = $this->getService(); + + $this->mockGuzzleResponse( + new Response( + status: SymfonyResponse::HTTP_OK, + body: FileTestUtil::getFileContents(__DIR__ . '/../../data/pickup-points/invalid-id-field-value.json') + ) + ); + + $service->getAllByRegion(RegionEnum::Cyprus); + } + + protected function getLoggerStream(): array + { + return [ + '[BOXNOW] Request - /v1/apms_hr-HR.json' => [ + 'endpoint' => '/v1/apms_hr-HR.json', + 'uri' => [ + 'path' => '/v1/apms_hr-HR.json', + 'query' => [], + ], + 'body' => [], + ], + '[BOXNOW] Response - /v1/apms_hr-HR.json' => [ + 'endpoint' => '/v1/apms_hr-HR.json', + 'uri' => [ + 'path' => '/v1/apms_hr-HR.json', + 'query' => [], + ], + 'response' => '--- HUGE CONTENT SKIPPED ---', + ], + ]; + } + + private function getService(): PickupPointService + { + return new PickupPointService($this->getClient(), $this->getSerializer()); + } +} diff --git a/tests/data/pickup-points/assert-valid-data-by-region.json b/tests/data/pickup-points/assert-valid-data-by-region.json new file mode 100644 index 0000000000..92b2c727fb --- /dev/null +++ b/tests/data/pickup-points/assert-valid-data-by-region.json @@ -0,0 +1,114 @@ +[ + { + "additionalAddress": "Λυκόβρυση", + "address": "Λεωφόρος Σοφοκλή Βενιζέλου 49", + "country": "GR", + "expectedDeliveryTime": "2025-06-27T19:00:00.000Z", + "id": "28", + "image": "https://storage.googleapis.com/boxnow-production-images/images/manager/30_11_2022/69366d64-218f-4575-8f2f-6cf571e5095f", + "latitude": 38.071742, + "longitude": 23.785242, + "name": "ΑΒ Λυκόβρυσης", + "note": "Επί της Λεωφόρου Σοφοκλή Βενιζέλου με κατεύθυνση το Ηράκλειο. Στο κατάστημα του ΑΒ Βασιλόπουλου δεξιά από την είσοδο.", + "postalCode": "14123", + "region": "el-GR", + "title": "Λ. ΣOΦOKΛH BENIZEΛOY 49, 14123", + "type": "apm" + }, + { + "additionalAddress": "Γαλάτσι", + "address": "Αιγοσθενών 78", + "country": "GR", + "expectedDeliveryTime": "2025-06-27T19:00:00.000Z", + "id": "5143", + "image": "https://storage.googleapis.com/boxnow-production-images/images/operations-manager/07_06_2024/4a62d29d-8510-4b37-955e-fc776c4cbd97", + "latitude": 38.02378602124016, + "longitude": 23.756451726304455, + "name": "e-Mob - Γαλάτσι", + "note": "Επί της οδού Αιγοσθένων, στο κατάστημα e-Mob.", + "postalCode": "11146", + "region": "el-GR", + "title": "AIΓOΣΘENΩN 78, 11146", + "type": "apm" + }, + { + "additionalAddress": "Λαμία", + "address": "Πύλου 24", + "country": "GR", + "expectedDeliveryTime": "2025-06-27T19:00:00.000Z", + "id": "7417", + "image": "https://storage.googleapis.com/boxnow-production-images/images/operations-manager/27_03_2024/4ccf4a19-1b85-49e9-bf7e-46d2f38b6ad4", + "latitude": 38.8932357729316, + "longitude": 22.41868934381607, + "name": "Γαλαξίας - 1ο ΧΛΜ Λαμίας Καρπενησίου", + "note": "Επί της οδού Πύλου 24, στο Super Market ΓΑΛΑΞΙΑΣ.", + "postalCode": "35100", + "region": "el-GR", + "title": "ΠYΛOY 24, 35100", + "type": "apm" + }, + { + "additionalAddress": "Μεταμόρφωση", + "address": "Αγ Νεκταρίου 69", + "country": "GR", + "expectedDeliveryTime": "2025-06-27T19:00:00.000Z", + "id": "7427", + "image": "https://storage.googleapis.com/boxnow-production-images/images/operations-manager/15_03_2024/82088a63-e40f-4a5d-8bea-beba68a8ea16", + "latitude": 38.05352105272671, + "longitude": 23.759888047413963, + "name": "Pet Vip Arena Market - Μεταμόρφωση", + "note": "Επί της οδού Αγ. Νεκταρίου, στο κατάστημα Arena Market.", + "postalCode": "14451", + "region": "el-GR", + "title": "AΓ NEKTAPIOY, 14451", + "type": "apm" + }, + { + "additionalAddress": " Άρτα", + "address": "Κόμβος A5 Ιονίας Οδού & EO Άρτας-Τρικάλων", + "country": "GR", + "expectedDeliveryTime": "2025-06-27T19:00:00.000Z", + "id": "7428", + "image": "https://storage.googleapis.com/boxnow-production-images/images/operations-manager/15_03_2024/dfe5bbe7-6333-4cde-b17a-b96a169690ef", + "latitude": 39.15787014093051, + "longitude": 21.012647900737115, + "name": "ΑΒ Κόμβος Ιονίας Οδού - Άρτα", + "note": "Στη συμβολη Α5 Ιονίας Οδού & ΕΟ Άρτας Τρικάλων, στο Super Market ΑΒ Βασιλόπουλος.", + "postalCode": "47100", + "region": "el-GR", + "title": "KOMBOΣ IONIAΣ OΔOY, 47100", + "type": "apm" + }, + { + "additionalAddress": "Εύοσμος", + "address": "25ης Μαρτίου 84-86", + "country": "GR", + "expectedDeliveryTime": "2025-06-27T19:00:00.000Z", + "id": "7436", + "image": "https://storage.googleapis.com/boxnow-production-images/images/operations-manager/11_06_2024/23cacf70-98e6-4f00-860d-024c87cd7aad", + "latitude": 40.6725665098987, + "longitude": 22.91599971354653, + "name": "Το παντοπωλείο της Σοφίας - Εύοσμος", + "note": "Επί της οδού 25ης Μαρτίου, στο Παντοπωλείο της Σοφίας.", + "postalCode": "56224", + "region": "el-GR", + "title": "25HΣ MAPTIOY 84-86, 56224", + "type": "apm" + }, + { + "additionalAddress": "Σταυρούπολη", + "address": "Κ. Κωνσταντινίδη & Αγ. Κωνσταντίνου 15", + "country": "GR", + "expectedDeliveryTime": "2025-06-27T19:00:00.000Z", + "id": "7439", + "image": "https://storage.googleapis.com/boxnow-production-images/images/operations-manager/22_11_2024/90d1d461-5ba5-4102-b9fa-d80326e6b9e8", + "latitude": 40.66777703688724, + "longitude": 22.927759187900392, + "name": "Woodncraft - Σταυρούπολη", + "note": "Στη συμβολή των οδών Κωσταντινίδη και Αγ. Κωσταντίνου, στο κατάστημα WoodNCraft.", + "postalCode": "56431", + "region": "el-GR", + "title": "AΓ KΩNΣTANTINOY 15, 56431", + "type": "apm" + } +] diff --git a/tests/data/pickup-points/success-by-region.json b/tests/data/pickup-points/success-by-region.json new file mode 100644 index 0000000000..4a099aa2ca --- /dev/null +++ b/tests/data/pickup-points/success-by-region.json @@ -0,0 +1,123 @@ +{ + "data": [ + { + "id": "28", + "type": "apm", + "lat": "38.071742", + "lng": "23.785242", + "addressLine1": "Λεωφόρος Σοφοκλή Βενιζέλου 49", + "addressLine2": "Λυκόβρυση", + "postalCode": "14123", + "title": "Λ. ΣOΦOKΛH BENIZEΛOY 49, 14123", + "name": "ΑΒ Λυκόβρυσης", + "country": "GR", + "image": "https://storage.googleapis.com/boxnow-production-images/images/manager/30_11_2022/69366d64-218f-4575-8f2f-6cf571e5095f", + "note": "Επί της Λεωφόρου Σοφοκλή Βενιζέλου με κατεύθυνση το Ηράκλειο. Στο κατάστημα του ΑΒ Βασιλόπουλου δεξιά από την είσοδο.", + "region": "el-GR", + "state": "boxnow-ready", + "expectedDeliveryTime": "2025-06-27T19:00:00.000Z" + }, + { + "id": "5143", + "type": "apm", + "lat": "38.02378602124016", + "lng": "23.756451726304455", + "addressLine1": "Αιγοσθενών 78", + "addressLine2": "Γαλάτσι", + "postalCode": "11146", + "title": "AIΓOΣΘENΩN 78, 11146", + "name": "e-Mob - Γαλάτσι", + "country": "GR", + "image": "https://storage.googleapis.com/boxnow-production-images/images/operations-manager/07_06_2024/4a62d29d-8510-4b37-955e-fc776c4cbd97", + "note": "Επί της οδού Αιγοσθένων, στο κατάστημα e-Mob.", + "region": "el-GR", + "state": "boxnow-ready", + "expectedDeliveryTime": "2025-06-27T19:00:00.000Z" + }, + { + "id": "7417", + "type": "apm", + "lat": "38.8932357729316", + "lng": "22.41868934381607", + "addressLine1": "Πύλου 24", + "addressLine2": "Λαμία", + "postalCode": "35100", + "title": "ΠYΛOY 24, 35100", + "name": "Γαλαξίας - 1ο ΧΛΜ Λαμίας Καρπενησίου", + "country": "GR", + "image": "https://storage.googleapis.com/boxnow-production-images/images/operations-manager/27_03_2024/4ccf4a19-1b85-49e9-bf7e-46d2f38b6ad4", + "note": "Επί της οδού Πύλου 24, στο Super Market ΓΑΛΑΞΙΑΣ.", + "region": "el-GR", + "state": "boxnow-ready", + "expectedDeliveryTime": "2025-06-27T19:00:00.000Z" + }, + { + "id": "7427", + "type": "apm", + "lat": "38.05352105272671", + "lng": "23.759888047413963", + "addressLine1": "Αγ Νεκταρίου 69", + "addressLine2": "Μεταμόρφωση", + "postalCode": "14451", + "title": "AΓ NEKTAPIOY, 14451", + "name": "Pet Vip Arena Market - Μεταμόρφωση", + "country": "GR", + "image": "https://storage.googleapis.com/boxnow-production-images/images/operations-manager/15_03_2024/82088a63-e40f-4a5d-8bea-beba68a8ea16", + "note": "Επί της οδού Αγ. Νεκταρίου, στο κατάστημα Arena Market.", + "region": "el-GR", + "state": "boxnow-ready", + "expectedDeliveryTime": "2025-06-27T19:00:00.000Z" + }, + { + "id": "7428", + "type": "apm", + "lat": "39.15787014093051", + "lng": "21.012647900737115", + "addressLine1": "Κόμβος A5 Ιονίας Οδού & EO Άρτας-Τρικάλων", + "addressLine2": " Άρτα", + "postalCode": "47100", + "title": "KOMBOΣ IONIAΣ OΔOY, 47100", + "name": "ΑΒ Κόμβος Ιονίας Οδού - Άρτα", + "country": "GR", + "image": "https://storage.googleapis.com/boxnow-production-images/images/operations-manager/15_03_2024/dfe5bbe7-6333-4cde-b17a-b96a169690ef", + "note": "Στη συμβολη Α5 Ιονίας Οδού & ΕΟ Άρτας Τρικάλων, στο Super Market ΑΒ Βασιλόπουλος.", + "region": "el-GR", + "state": "boxnow-ready", + "expectedDeliveryTime": "2025-06-27T19:00:00.000Z" + }, + { + "id": "7436", + "type": "apm", + "lat": "40.6725665098987", + "lng": "22.91599971354653", + "addressLine1": "25ης Μαρτίου 84-86", + "addressLine2": "Εύοσμος", + "postalCode": "56224", + "title": "25HΣ MAPTIOY 84-86, 56224", + "name": "Το παντοπωλείο της Σοφίας - Εύοσμος", + "country": "GR", + "image": "https://storage.googleapis.com/boxnow-production-images/images/operations-manager/11_06_2024/23cacf70-98e6-4f00-860d-024c87cd7aad", + "note": "Επί της οδού 25ης Μαρτίου, στο Παντοπωλείο της Σοφίας.", + "region": "el-GR", + "state": "boxnow-ready", + "expectedDeliveryTime": "2025-06-27T19:00:00.000Z" + }, + { + "id": "7439", + "type": "apm", + "lat": "40.66777703688724", + "lng": "22.927759187900392", + "addressLine1": "Κ. Κωνσταντινίδη & Αγ. Κωνσταντίνου 15", + "addressLine2": "Σταυρούπολη", + "postalCode": "56431", + "title": "AΓ KΩNΣTANTINOY 15, 56431", + "name": "Woodncraft - Σταυρούπολη", + "country": "GR", + "image": "https://storage.googleapis.com/boxnow-production-images/images/operations-manager/22_11_2024/90d1d461-5ba5-4102-b9fa-d80326e6b9e8", + "note": "Στη συμβολή των οδών Κωσταντινίδη και Αγ. Κωσταντίνου, στο κατάστημα WoodNCraft.", + "region": "el-GR", + "state": "boxnow-ready", + "expectedDeliveryTime": "2025-06-27T19:00:00.000Z" + } + ] +}