diff --git a/CHANGELOG.md b/CHANGELOG.md index f85d849..4a90b12 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 4.0.0-beta.4 - 2021-11-25 + +### Added + +- `mdpClassic` and `mdpSpectrum` attributes to `BasicOrder` and `Order` entities +- `Order` client documentation + ## 4.0.0-beta.3 - 2021-11-25 ### Added diff --git a/README.md b/README.md index bf0de1d..7d45c6d 100644 --- a/README.md +++ b/README.md @@ -135,5 +135,4 @@ List of custom Exceptions thrown in this client can be found [here](doc/Exceptio ### This is still a Beta release, and some features are missing or incomplete -- [ ] Order client documentation and examples - [ ] Transports v2 support diff --git a/doc/Order.md b/doc/Order.md index 94138d1..3704d30 100644 --- a/doc/Order.md +++ b/doc/Order.md @@ -4,6 +4,262 @@ To see example of initialization, please look at [Implementation](../README.md#implementation) part of our [README](../README.md) -## TODO add documentation +## Get list of orders + +Method expects [?Filter](../src/Filter/Filter.php) and returns [BasicOrderList](../src/Order/Entity/BasicOrderList.php) containing [BasicOrder](../src/Order/Entity/BasicOrder.php) entity. + +```php +/** @var MpApiClient\Common\Interfaces\OrderClientInterface $orderClient */ +$orderList = $orderClient->list(null); +echo json_encode($orderList, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); +``` + +Example above prints out + +```json +{ + "paging": { + "total": 940, + "pages": 10, + "size": 40, + "page": 10 + }, + "data": [ + { + "id": 10085339302, + "purchaseId": 100853393, + "customerId": 1089641061, + "customer": "Firstname Surname", + "cod": 154, + "paymentType": "A", + "shipDate": "2021-11-25 00:00:00", + "trackingNumber": null, + "trackingUrl": null, + "deliveredAt": null, + "status": "open", + "confirmed": false, + "test": false, + "mdp": true, + "mdpSpectrum": true, + "mdpClassic": false + }, + { + "id": 10085192603, + "purchaseId": 100851926, + "customerId": 1100012571, + "customer": "Firstname Surname", + "cod": 479, + "paymentType": "A", + "shipDate": "2021-11-24 00:00:00", + "trackingNumber": null, + "trackingUrl": null, + "deliveredAt": null, + "status": "open", + "confirmed": false, + "test": false, + "mdp": true, + "mdpSpectrum": true, + "mdpClassic": false + }, + { + "id": 10084686702, + "purchaseId": 100846867, + "customerId": 1095774003, + "customer": "Firstname Surname", + "cod": 488, + "paymentType": "A", + "shipDate": "2021-11-19 00:00:00", + "trackingNumber": null, + "trackingUrl": null, + "deliveredAt": null, + "status": "open", + "confirmed": false, + "test": false, + "mdp": true, + "mdpSpectrum": true, + "mdpClassic": false + }, + ... + ] +} +``` + +## Get order detail + +Method expects `order` ID and returns [Order](../src/Order/Entity/Order.php) entity. + +```php +/** @var MpApiClient\Common\Interfaces\OrderClientInterface $orderClient */ +$orderDetail = $orderClient->get(12345678901); +echo json_encode($orderDetail, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); +``` + +Example above prints out + +```json +{ + "id": 12345678901, + "purchaseId": 123456789, + "currency": "CZK", + "deliveryPrice": 29, + "codPrice": 39, + "cod": 1867, + "discount": 0, + "paymentType": "A", + "deliveryMethod": "20", + "deliveryMethodId": "23", + "branchId": 23, + "branches": { + "branchId": 23, + "secondaryBranchId": null, + "lastChange": null + }, + "trackingNumber": null, + "trackingUrl": null, + "shipDate": "2019-07-25 00:00:00", + "deliveryDate": "2019-07-26 00:00:00", + "deliveredAt": null, + "firstDeliveryAttempt": null, + "customer": { + "customerId": 1101334728, + "name": "Firstname Surname", + "company": null, + "phone": "+420721123456", + "email": "a@a.com", + "street": "Pražská 121", + "city": "Pelhřimov", + "zip": "39301", + "country": "CZ" + }, + "confirmed": false, + "status": "open", + "items": [ + { + "id": "pCL00275", + "articleId": 100001054382, + "quantity": 1, + "price": 1799, + "vat": 21, + "commission": 15, + "title": "Chloé - EDP 75 ml", + "serialNumbers": [] + } + ], + "test": false, + "mdp": true, + "mdpClassic": true, + "mdpSpectrum": false, + "readyToReturn": false, + "shipped": null, + "open": "2019-07-25 16:12:14", + "blocked": "2019-07-25 16:07:31", + "lost": null, + "returned": null, + "cancelled": null, + "delivered": null, + "shipping": null, + "ulozenkaStatusHistory": [] +} +``` + +## Get order statistics + +Method expects `order` ID and returns [Stats](../src/Order/Entity/Stats.php) entity. + +```php +/** @var MpApiClient\Common\Interfaces\OrderClientInterface $orderClient */ +$orderDetail = $orderClient->stats(10); +echo json_encode($orderDetail, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); +``` + +Example above prints out + +```json +{ + "blocked": 49, + "open": 8, + "shipping": 0, + "shipped": 0, + "cancelled": 1, + "delivered": 0, + "lost": 0, + "returned": 0 +} +``` + +## Confirm order + +Method expects `order` ID and does not return anything. + +```php +/** @var MpApiClient\Common\Interfaces\OrderClientInterface $orderClient */ +$orderClient->confirmOrder(1234567890); +``` + +## Change order status + +Method expects `order` ID and [StatusRequest](../src/Order/DTO/StatusRequest.php) DTO and does not return anything. + +```php +/** @var MpApiClient\Common\Interfaces\OrderClientInterface $orderClient */ +$statusRequest = new StatusRequest(StatusEnum::shipping()); +$statusRequest->setTracking('ABC123456', 'https://tracking.company.com/id/ABC123456'); +$orderClient->setStatus(1234567890, $statusRequest); +``` + +## Set tracking for shipped order + +Method expects `order` ID and [StatusRequest](../src/Order/DTO/StatusRequest.php) DTO and does not return anything. + +```php +/** @var MpApiClient\Common\Interfaces\OrderClientInterface $orderClient */ +$tracking = new Tracking('ABC123456', 'https://tracking.company.com/id/ABC123456'); +$orderClient->setTracking(1234567890, $tracking); +``` + +## Set serial numbers for order item + +Method expects `order` and `orderItem` IDs and variable amount of serial numbers and does not return anything. + +```php +/** @var MpApiClient\Common\Interfaces\OrderClientInterface $orderClient */ +$orderClient->setItemSerialNumbers(1234567890, 1234567, 'SN12345', 'SN23456'); +``` + +## Print labels for multiple orders + +Method expects [ShippingLabelRequest](../src/Order/DTO/ShippingLabelRequest.php) DTO and returns [Labels](../src/Order/Entity/Labels.php) entity. + +```php +/** @var MpApiClient\Common\Interfaces\OrderClientInterface $orderClient */ +$labelRequest = new ShippingLabelRequest(ShippingLabelRequest::TYPE_PDF, 1, 4); +$labelRequest->addLabel(123456666, 2); +$labelRequest->addLabel(123456777, 1); +$labels = $orderClient->createShippingLabels($labelRequest); +echo json_encode($labels, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); +``` + +Example above prints out + +```json +{ + "orders": [ + { + "orderId": 123456666, + "barcodes": [ + "14IS50856666*001001", + "14IS50856666*001002" + ] + }, + { + "orderId": 123456777, + "barcodes": [ + "14IS50857777*001001" + ] + } + ], + "labelsRaw": "JVBERi0xLjQKJeLjz9MKMyAwI....PgpzdGFydHhyZWYKNTAyNTcKJSVFT0Y=" +} +``` ### See more examples [here](../example/Order.php) diff --git a/example/Order.php b/example/Order.php index a304506..4f4b039 100644 --- a/example/Order.php +++ b/example/Order.php @@ -1,14 +1,16 @@ orders()->list(null); -echo json_encode($orderList, JSON_PRETTY_PRINT); - -// 4. Send query to order list endpoint with filter where -// - `status` field is equal to `open` -// - `id` field is between 100 and 10000 (inclusive) -// - results are sorted by `id` field in descending direction -$filter = new Filter(); -$filter->addFilterItem(FilterItem::create("status", StatusEnum::OPEN()->getValue(), FilterOperatorEnum::EQUAL())); -$filter->addFilterItem(FilterItem::createInterval("cod", "100", "10000")); -$filter->addSortColumn('id', Filter::DIRECTION_DESC); - -$filteredOrderList = $client->orders()->list($filter); -// $filteredOrderList->enableAutoload(true); -echo json_encode($filteredOrderList, JSON_PRETTY_PRINT); - -// 5. Get single order by ID -$orderDetail = $client->orders()->get($orderId); -echo json_encode($orderDetail, JSON_PRETTY_PRINT); - -// 6. Get order statistics for past 14 days -$orderStats = $client->orders()->stats(14); -echo json_encode($orderStats, JSON_PRETTY_PRINT); - -// 7. Confirm/acknowledge new changes on an order (unconfirmed orders can not have their status changed) -$client->orders()->confirmOrder($orderId); - -// 8. Update order status -$statusRequest = new StatusRequest(StatusEnum::shipping()); -$statusRequest->setTracking('ABC123456', 'https://tracking.company.com/id/ABC123456'); -$client->orders()->setStatus($orderId, $statusRequest); - -// 9. Set tracking for shipped order (should be set in one request during status update) -$client->orders()->setItemSerialNumbers($orderId, 1234567, 'SN12345', 'SN23456'); - -// 10. Get order shipping labels to print on the box for two orders -$labelRequest = new ShippingLabelRequest(ShippingLabelRequest::TYPE_PDF, 1, 4); -$labelRequest->addLabel($orderId, 2); -$labelRequest->addLabel($orderId2, 1); -$labels = $client->orders()->createShippingLabels($labelRequest); -echo $labels->getLabelsRaw(); +// +// Get order list +// + +try { + // Create a filter where: + // - `status` field is equal to `open` + // - `id` field is between 100 and 10000 (inclusive) + // - results are sorted by `id` field in descending direction + $filter = new Filter(); + $filter->addFilterItem(FilterItem::create('status', StatusEnum::OPEN()->getValue(), FilterOperatorEnum::EQUAL())); + $filter->addFilterItem(FilterItem::createInterval('cod', '100', '10000')); + $filter->addSortColumn('id', Filter::DIRECTION_DESC); + + // list orders with custom filter (filter is optional) + $orderList = $client->orders()->list($filter); + + // enable autoload, to iterate over all results, not only first page + $orderList->enableAutoload(); + + // Print all orders as json object + echo json_encode($orderList, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); + + // Get all orders as array + var_dump($orderList->jsonSerialize()); + + // Iterate over the returned list + foreach ($orderList as $order) { + echo 'Id: ' . $order->getId() . PHP_EOL; + echo 'Purchase id: ' . $order->getPurchaseId() . PHP_EOL; + echo 'Customer id: ' . $order->getCustomerId() . PHP_EOL; + echo 'Customer: ' . $order->getCustomer() . PHP_EOL; + echo 'Status: ' . $order->getStatus()->getValue() . PHP_EOL; + echo 'Tracking number: ' . $order->getTrackingNumber() . PHP_EOL; + echo 'Tracking url: ' . $order->getTrackingUrl() . PHP_EOL; + echo 'Payment type: ' . $order->getPaymentType() . PHP_EOL; + echo 'COD: ' . $order->getCod() . PHP_EOL; + echo 'MDP: ' . $order->isMdp() ? 'true' : 'false' . PHP_EOL; + echo PHP_EOL; + } +} catch (MpApiException | Exception $e) { + echo 'Unexpected error occurred while loading order list: ' . $e->getMessage(); +} + +// +// Get order detail +// + +try { + $orderDetail = $client->orders()->get(1234567890); + + // Print order as json object + echo json_encode($orderDetail, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); + + // Get order as array + var_dump($orderDetail->jsonSerialize()); + + // Print some order data + echo 'Customer id: ' . $orderDetail->getCustomer()->getCustomerId() . PHP_EOL; + echo 'Customer Name: ' . $orderDetail->getCustomer()->getName() . PHP_EOL; + echo 'Payment type: ' . $orderDetail->getPaymentType() . PHP_EOL; + echo 'Tracking url: ' . $orderDetail->getTrackingUrl() . PHP_EOL; + echo 'Currency: ' . $orderDetail->getCurrency() . PHP_EOL; + echo 'COD: ' . $orderDetail->getCod() . PHP_EOL; + echo 'Status: ' . $orderDetail->getStatus()->getValue() . PHP_EOL; + echo PHP_EOL; +} catch (MpApiException | Exception $e) { + echo 'Unexpected error occurred while loading order detail: ' . $e->getMessage(); +} + +// +// Get order statistics +// + +try { + $orderStats = $client->orders()->stats(10); + + // Print order statistics as json object + echo json_encode($orderStats, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); + + // Get order statistics as array + var_dump($orderStats->jsonSerialize()); + + // Print order statistics + echo 'Blocked: ' . $orderStats->getBlocked() . PHP_EOL; + echo 'Open: ' . $orderStats->getOpen() . PHP_EOL; + echo 'Shipping: ' . $orderStats->getShipping() . PHP_EOL; + echo 'Shipped: ' . $orderStats->getShipped() . PHP_EOL; + echo 'Cancelled: ' . $orderStats->getCancelled() . PHP_EOL; + echo 'Delivered: ' . $orderStats->getDelivered() . PHP_EOL; + echo 'Lost: ' . $orderStats->getLost() . PHP_EOL; + echo 'Returned: ' . $orderStats->getReturned() . PHP_EOL; + echo PHP_EOL; +} catch (MpApiException $e) { + echo 'Unexpected error occurred while loading order statistics: ' . $e->getMessage(); +} + +// +// Confirm order +// - unconfirmed orders can not have their status changed +// + +try { + $client->orders()->confirmOrder(1234567890); +} catch (MpApiException $e) { + echo 'Unexpected error occurred during order confirmation: ' . $e->getMessage(); +} + +// +// Change order status +// + +try { + $statusRequest = new StatusRequest(StatusEnum::shipping()); + $statusRequest->setConfirmed(true); // order may be confirmed at the same time the status is being changed + $statusRequest->setTracking('ABC123456', 'https://tracking.company.com/id/ABC123456'); + $client->orders()->setStatus(1234567890, $statusRequest); +} catch (MpApiException $e) { + echo 'Unexpected error occurred during order status change: ' . $e->getMessage(); +} + +// +// Set tracking for shipped order +// - should be set in one request during status update, not additionally! +// + +try { + $tracking = new Tracking('ABC123456', 'https://tracking.company.com/id/ABC123456'); + $client->orders()->setTracking(1234567890, $tracking); +} catch (MpApiException $e) { + echo 'Unexpected error occurred during order status change: ' . $e->getMessage(); +} + +// +// Set serial numbers for order item +// + +try { + $client->orders()->setItemSerialNumbers(1234567890, 1234567, 'SN12345', 'SN23456'); +} catch (MpApiException $e) { + echo 'Unexpected error occurred while setting order item serial numbers: ' . $e->getMessage(); +} + +// +// Create shipping labels for order +// + +try { + $labelRequest = new ShippingLabelRequest(ShippingLabelRequest::TYPE_PDF, 1, 4); + $labelRequest->addLabel(123456666, 2); + $labelRequest->addLabel(10083920202, 1); + $labels = $client->orders()->createShippingLabels($labelRequest); + + // Print labels as json object + echo json_encode($labels, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE); + + // Get labels as array + var_dump($labels->jsonSerialize()); + + // Iterate order list and show parcel barcodes for every order + foreach ($labels->getOrders() as $labelsOrder) { + echo 'Order id: ' . $labelsOrder->getOrderId() . PHP_EOL; + echo 'Barcodes: ' . implode(', ', $labelsOrder->getBarcodes()) . PHP_EOL; + echo PHP_EOL; + } + + // Print raw base64 encoded PDF or ZPL document + echo $labels->getLabelsRaw(); +} catch (MpApiException $e) { + echo 'Unexpected error occurred during order labels creation: ' . $e->getMessage(); +} diff --git a/src/Order/Entity/BasicOrder.php b/src/Order/Entity/BasicOrder.php index e6b7662..620cc15 100644 --- a/src/Order/Entity/BasicOrder.php +++ b/src/Order/Entity/BasicOrder.php @@ -27,6 +27,8 @@ final class BasicOrder implements JsonSerializable private bool $confirmed; private bool $test; private bool $mdp; + private bool $mdpSpectrum; + private bool $mdpClassic; private function __construct( int $id, @@ -42,7 +44,9 @@ private function __construct( StatusEnum $status, bool $confirmed, bool $test, - bool $mdp + bool $mdp, + bool $mdpClassic, + bool $mdpSpectrum ) { $this->id = $id; $this->purchaseId = $purchaseId; @@ -58,6 +62,8 @@ private function __construct( $this->confirmed = $confirmed; $this->test = $test; $this->mdp = $mdp; + $this->mdpClassic = $mdpClassic; + $this->mdpSpectrum = $mdpSpectrum; } /** @@ -83,6 +89,8 @@ public static function createFromApi(array $data): self (bool) $data['confirmed'], (bool) $data['test'], (bool) $data['mdp'], + (bool) $data['mdp_classic'], + (bool) $data['mdp_spectrum'], ); } @@ -156,4 +164,14 @@ public function isMdp(): bool return $this->mdp; } + public function isMdpSpectrum(): bool + { + return $this->mdpSpectrum; + } + + public function isMdpClassic(): bool + { + return $this->mdpClassic; + } + } diff --git a/src/Order/Entity/Order.php b/src/Order/Entity/Order.php index 8be2183..88cb192 100644 --- a/src/Order/Entity/Order.php +++ b/src/Order/Entity/Order.php @@ -37,6 +37,8 @@ final class Order implements JsonSerializable private ItemIterator $items; private bool $test; private bool $mdp; + private bool $mdpClassic; + private bool $mdpSpectrum; private bool $readyToReturn; private ?DateTimeInterface $shipped; private ?DateTimeInterface $open; @@ -73,6 +75,8 @@ private function __construct( ItemIterator $items, bool $test, bool $mdp, + bool $mdpClassic, + bool $mdpSpectrum, bool $readyToReturn, ?DateTimeInterface $shipped, ?DateTimeInterface $open, @@ -108,6 +112,8 @@ private function __construct( $this->items = $items; $this->test = $test; $this->mdp = $mdp; + $this->mdpClassic = $mdpClassic; + $this->mdpSpectrum = $mdpSpectrum; $this->readyToReturn = $readyToReturn; $this->shipped = $shipped; $this->open = $open; @@ -153,6 +159,8 @@ public static function createFromApi(array $data): self ItemIterator::createFromApi($data['items']), (bool) $data['test'], (bool) $data['mdp'], + (bool) $data['mdp_classic'], + (bool) $data['mdp_spectrum'], (bool) $data['ready_to_return'], InputDataUtil::getNullableDate($data, 'shipped'), InputDataUtil::getNullableDate($data, 'open'), @@ -286,6 +294,16 @@ public function isMdp(): bool return $this->mdp; } + public function isMdpClassic(): bool + { + return $this->mdpClassic; + } + + public function isMdpSpectrum(): bool + { + return $this->mdpSpectrum; + } + public function isReadyToReturn(): bool { return $this->readyToReturn; diff --git a/tests/functional/OrderClientCest.php b/tests/functional/OrderClientCest.php index 1c89a86..6d03ef9 100644 --- a/tests/functional/OrderClientCest.php +++ b/tests/functional/OrderClientCest.php @@ -77,6 +77,8 @@ public function testList(FunctionalTester $I): void $I->assertIsBool($order->isConfirmed()); $I->assertIsBool($order->isTest()); $I->assertIsBool($order->isMdp()); + $I->assertIsBool($order->isMdpClassic()); + $I->assertIsBool($order->isMdpSpectrum()); } } @@ -145,6 +147,8 @@ public function testGet(FunctionalTester $I): void $I->assertEquals($orderArr['test'], $order->isTest()); $I->assertEquals($orderArr['mdp'], $order->isMdp()); + $I->assertEquals($orderArr['mdp_classic'], $order->isMdpClassic()); + $I->assertEquals($orderArr['mdp_spectrum'], $order->isMdpSpectrum()); $I->assertEquals($orderArr['ready_to_return'], $order->isReadyToReturn()); $I->assertEquals($orderArr['shipped'] ?? null, $order->getShipped()); $I->assertEquals($orderArr['open'] ?? null, $order->getOpen()); diff --git a/tests/functional/bootstrap.php b/tests/functional/bootstrap.php index 5136b52..532b2bb 100644 --- a/tests/functional/bootstrap.php +++ b/tests/functional/bootstrap.php @@ -243,6 +243,8 @@ ], 'test' => false, 'mdp' => false, + 'mdp_classic' => false, + 'mdp_spectrum' => false, 'ready_to_return' => true, 'shipped' => new DateTime('2020-01-09 12:08:56'), 'open' => new DateTime('2020-01-09 13:33:49'),