From 55d8a095e5da33d405c3b9abcce3fb9079db3d44 Mon Sep 17 00:00:00 2001 From: Shady Khattab Date: Mon, 4 Dec 2017 16:02:42 +0100 Subject: [PATCH 1/2] :sparkles: Added customs information to shipment and updated factories --- src/Authentication/AuthenticatorInterface.php | 2 +- src/MyParcelComApi.php | 4 +- src/Resources/Customs.php | 127 ++++++++++++++ src/Resources/CustomsItem.php | 163 ++++++++++++++++++ src/Resources/File.php | 1 - src/Resources/Interfaces/CustomsInterface.php | 79 +++++++++ .../Interfaces/CustomsItemInterface.php | 83 +++++++++ .../Interfaces/ShipmentInterface.php | 11 ++ src/Resources/ResourceFactory.php | 130 ++++++++++++-- src/Resources/Shipment.php | 25 ++- 10 files changed, 609 insertions(+), 16 deletions(-) create mode 100644 src/Resources/Customs.php create mode 100644 src/Resources/CustomsItem.php create mode 100644 src/Resources/Interfaces/CustomsInterface.php create mode 100644 src/Resources/Interfaces/CustomsItemInterface.php diff --git a/src/Authentication/AuthenticatorInterface.php b/src/Authentication/AuthenticatorInterface.php index 6d3a1d15..4e08acbc 100644 --- a/src/Authentication/AuthenticatorInterface.php +++ b/src/Authentication/AuthenticatorInterface.php @@ -10,7 +10,7 @@ interface AuthenticatorInterface const HEADER_ACCEPT = 'Accept'; const MIME_TYPE_JSONAPI = 'application/vnd.api+json'; const GRANT_CLIENT_CREDENTIALS = 'client_credentials'; - const SCOPES = ''; + const SCOPES = 'shipments.show shipments.manage shops.show'; /** * Authenticate with the OAuth2 server and return the header to be used in diff --git a/src/MyParcelComApi.php b/src/MyParcelComApi.php index 664cd2d3..c5d47b6b 100644 --- a/src/MyParcelComApi.php +++ b/src/MyParcelComApi.php @@ -6,8 +6,6 @@ use GuzzleHttp\ClientInterface; use GuzzleHttp\Exception\RequestException; use GuzzleHttp\Promise\PromiseInterface; -use function GuzzleHttp\Psr7\parse_response; -use function GuzzleHttp\Psr7\str; use GuzzleHttp\RequestOptions; use MyParcelCom\Sdk\Authentication\AuthenticatorInterface; use MyParcelCom\Sdk\Exceptions\InvalidResourceException; @@ -29,6 +27,8 @@ use Symfony\Component\Cache\Simple\FilesystemCache; use function GuzzleHttp\Promise\promise_for; use function GuzzleHttp\Promise\unwrap; +use function GuzzleHttp\Psr7\parse_response; +use function GuzzleHttp\Psr7\str; class MyParcelComApi implements MyParcelComApiInterface { diff --git a/src/Resources/Customs.php b/src/Resources/Customs.php new file mode 100644 index 00000000..6fe7800d --- /dev/null +++ b/src/Resources/Customs.php @@ -0,0 +1,127 @@ +contentType; + } + + /** + * {@inheritdoc} + */ + public function setContentType($contentType) + { + $this->contentType = $contentType; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getInvoiceNumber() + { + return $this->invoiceNumber; + } + + /** + * {@inheritdoc} + */ + public function setInvoiceNumber($invoiceNumber) + { + $this->invoiceNumber = $invoiceNumber; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getItems() + { + return $this->items; + } + + /** + * {@inheritdoc} + */ + public function addItem(CustomsItemInterface $item) + { + $this->items[] = $item; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function setItems(array $items) + { + $this->items = []; + + array_walk($items, function (CustomsItemInterface $item) { + $this->addItem($item); + }); + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getNonDelivery() + { + return $this->nonDelivery; + } + + /** + * {@inheritdoc} + */ + public function setNonDelivery($nonDelivery) + { + $this->nonDelivery = $nonDelivery; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getIncoterm() + { + return $this->incoterm; + } + + /** + * {@inheritdoc} + */ + public function setIncoterm($incoterm) + { + $this->incoterm = $incoterm; + + return $this; + } +} diff --git a/src/Resources/CustomsItem.php b/src/Resources/CustomsItem.php new file mode 100644 index 00000000..c024084e --- /dev/null +++ b/src/Resources/CustomsItem.php @@ -0,0 +1,163 @@ + null, + self::CURRENCY => null, + ]; + /** @var string */ + private $originCountryCode; + + /** + * @param string $sku + * @return $this + */ + public function setSku($sku) + { + $this->sku = $sku; + + return $this; + } + + /** + * @return string + */ + public function getSku() + { + return $this->sku; + } + + /** + * @param string $description + * @return $this + */ + public function setDescription($description) + { + $this->description = $description; + + return $this; + } + + /** + * @return string + */ + public function getDescription() + { + return $this->description; + } + + /** + * @param string $hsCode + * @return $this + */ + public function setHsCode($hsCode) + { + $this->hsCode = $hsCode; + + return $this; + } + + /** + * @return string + */ + public function getHsCode() + { + return $this->hsCode; + } + + /** + * @param int $quantity + * @return $this + */ + public function setQuantity($quantity) + { + $this->quantity = (int)$quantity; + + return $this; + } + + /** + * @return int + */ + public function getQuantity() + { + return $this->quantity; + } + + /** + * @param int $value + * @return $this + */ + public function setItemValue($value) + { + $this->itemValue[self::AMOUNT] = (int)$value; + + return $this; + } + + /** + * @return int + */ + public function getItemValue() + { + return $this->itemValue[self::AMOUNT]; + } + + /** + * @param string $currency + * @return $this + */ + public function setCurrency($currency) + { + $this->itemValue[self::CURRENCY] = $currency; + + return $this; + } + + /** + * @return string + */ + public function getCurrency() + { + return $this->itemValue[self::CURRENCY]; + } + + /** + * @param string $countryCode + * @return $this + */ + public function setOriginCountryCode($countryCode) + { + $this->originCountryCode = $countryCode; + + return $this; + } + + /** + * @return string + */ + public function getOriginCountryCode() + { + return $this->originCountryCode; + } +} diff --git a/src/Resources/File.php b/src/Resources/File.php index 26cd5197..b1f6f68b 100644 --- a/src/Resources/File.php +++ b/src/Resources/File.php @@ -7,7 +7,6 @@ use MyParcelCom\Sdk\Resources\Traits\JsonSerializable; use Psr\Http\Message\StreamInterface; - class File implements FileInterface { use JsonSerializable; diff --git a/src/Resources/Interfaces/CustomsInterface.php b/src/Resources/Interfaces/CustomsInterface.php new file mode 100644 index 00000000..dbcca7cd --- /dev/null +++ b/src/Resources/Interfaces/CustomsInterface.php @@ -0,0 +1,79 @@ + Carrier::class, - ResourceInterface::TYPE_CONTRACT => Contract::class, - ResourceInterface::TYPE_PUDO_LOCATION => PickUpDropOffLocation::class, - ResourceInterface::TYPE_REGION => Region::class, - ResourceInterface::TYPE_SHOP => Shop::class, - ResourceInterface::TYPE_SERVICE_OPTION => ServiceOption::class, - ResourceInterface::TYPE_SERVICE_INSURANCE => ServiceInsurance::class, - ResourceInterface::TYPE_STATUS => Status::class, + ResourceInterface::TYPE_CARRIER => Carrier::class, + ResourceInterface::TYPE_CONTRACT => Contract::class, + ResourceInterface::TYPE_PUDO_LOCATION => PickUpDropOffLocation::class, + ResourceInterface::TYPE_REGION => Region::class, + ResourceInterface::TYPE_SHOP => Shop::class, + ResourceInterface::TYPE_STATUS => Status::class, AddressInterface::class => Address::class, CarrierInterface::class => Carrier::class, ContractInterface::class => Contract::class, + CustomsInterface::class => Customs::class, OpeningHourInterface::class => OpeningHour::class, PhysicalPropertiesInterface::class => PhysicalProperties::class, PickUpDropOffLocationInterface::class => PickUpDropOffLocation::class, @@ -53,8 +54,6 @@ class ResourceFactory implements ResourceFactoryInterface, ResourceProxyInterfac RegionInterface::class => Region::class, ShipmentInterface::class => Shipment::class, ShopInterface::class => Shop::class, - ServiceOptionInterface::class => ServiceOption::class, - ServiceInsuranceInterface::class => ServiceInsurance::class, StatusInterface::class => Status::class, ]; @@ -66,7 +65,10 @@ public function __construct() $shipmentFactory = [$this, 'shipmentFactory']; $serviceFactory = [$this, 'serviceFactory']; $serviceGroupFactory = [$this, 'serviceGroupFactory']; + $serviceOptionFactory = [$this, 'serviceOptionFactory']; + $serviceInsuranceFactory = [$this, 'serviceInsuranceFactory']; $fileFactory = [$this, 'fileFactory']; + $customsItemFactory = [$this, 'customsItemFactory']; $this->setFactoryForType(ResourceInterface::TYPE_SHIPMENT, $shipmentFactory); $this->setFactoryForType(ShipmentInterface::class, $shipmentFactory); @@ -77,8 +79,16 @@ public function __construct() $this->setFactoryForType(ResourceInterface::TYPE_SERVICE_GROUP, $serviceGroupFactory); $this->setFactoryForType(ServiceGroupInterface::class, $serviceGroupFactory); + $this->setFactoryForType(ResourceInterface::TYPE_SERVICE_OPTION, $serviceOptionFactory); + $this->setFactoryForType(ServiceOptionInterface::class, $serviceOptionFactory); + + $this->setFactoryForType(ResourceInterface::TYPE_SERVICE_INSURANCE, $serviceInsuranceFactory); + $this->setFactoryForType(ServiceInsuranceInterface::class, $serviceInsuranceFactory); + $this->setFactoryForType(ResourceInterface::TYPE_FILE, $fileFactory); $this->setFactoryForType(FileInterface::class, $fileFactory); + + $this->setFactoryForType(CustomsItemInterface::class, $customsItemFactory); } /** @@ -118,6 +128,22 @@ protected function shipmentFactory($type, array &$attributes) unset($attributes['status']); } + if (isset($attributes['price']['amount'])) { + $shipment->setPrice($attributes['price']['amount']); + $shipment->setCurrency($attributes['price']['currency']); + + unset($attributes['price']); + } + + if (isset($attributes['insurance']['amount'])) { + $shipment->setInsuranceAmount($attributes['insurance']['amount']); + if (!$shipment->getCurrency()) { + $shipment->setCurrency($attributes['insurance']['currency']); + } + + unset($attributes['insurance']); + } + return $shipment; } @@ -200,6 +226,69 @@ protected function serviceGroupFactory($type, &$attributes) return $serviceGroup; } + /** + * ServiceOption factory method. + * + * @param string $type + * @param array $attributes + * @return ServiceOption + */ + protected function serviceOptionFactory($type, &$attributes) + { + $serviceOption = new ServiceOption(); + + if (isset($attributes['attributes']['price']['amount'])) { + $serviceOption->setPrice($attributes['attributes']['price']['amount']); + $serviceOption->setCurrency($attributes['attributes']['price']['currency']); + + unset($attributes['attributes']['price']); + } + + if (isset($attributes['attributes'])) { + $attributes += $attributes['attributes']; + + unset($attributes['attributes']); + } + + return $serviceOption; + } + + /** + * ServiceInsurance factory method. + * + * @param string $type + * @param array $attributes + * @return ServiceInsurance + */ + protected function serviceInsuranceFactory($type, &$attributes) + { + $serviceInsurance = new ServiceInsurance(); + + if (isset($attributes['attributes']['price']['amount'])) { + $serviceInsurance->setPrice($attributes['attributes']['price']['amount']); + $serviceInsurance->setCurrency($attributes['attributes']['price']['currency']); + + unset($attributes['attributes']['price']); + } + + if (isset($attributes['attributes']['covered']['amount'])) { + $serviceInsurance->setCovered($attributes['attributes']['covered']['amount']); + if (!$serviceInsurance->getCurrency()) { + $serviceInsurance->setCurrency($attributes['attributes']['covered']['currency']); + } + + unset($attributes['attributes']['covered']); + } + + if (isset($attributes['attributes'])) { + $attributes += $attributes['attributes']; + + unset($attributes['attributes']); + } + + return $serviceInsurance; + } + /** * Factory method for creating file resources, adds proxy streams to the * file for requesting the file data. @@ -226,6 +315,27 @@ protected function fileFactory($type, &$attributes) return $file; } + /** + * Factory for creating a customs item. + * + * @param $type + * @param $attributes + * @return CustomsItem + */ + protected function customsItemFactory($type, &$attributes) + { + $item = new CustomsItem(); + + if (isset($attributes['item_value']['amount'])) { + $item->setItemValue($attributes['item_value']['amount']); + $item->setCurrency($attributes['item_value']['currency']); + + unset($attributes['item_value']); + } + + return $item; + } + /** * {@inheritdoc} */ diff --git a/src/Resources/Shipment.php b/src/Resources/Shipment.php index 0b1be015..6517d4c6 100644 --- a/src/Resources/Shipment.php +++ b/src/Resources/Shipment.php @@ -5,6 +5,7 @@ use MyParcelCom\Sdk\Exceptions\MyParcelComException; use MyParcelCom\Sdk\Resources\Interfaces\AddressInterface; use MyParcelCom\Sdk\Resources\Interfaces\ContractInterface; +use MyParcelCom\Sdk\Resources\Interfaces\CustomsInterface; use MyParcelCom\Sdk\Resources\Interfaces\FileInterface; use MyParcelCom\Sdk\Resources\Interfaces\PhysicalPropertiesInterface; use MyParcelCom\Sdk\Resources\Interfaces\ResourceInterface; @@ -32,6 +33,7 @@ class Shipment implements ShipmentInterface const ATTRIBUTE_PICKUP = 'pickup_location'; const ATTRIBUTE_PICKUP_CODE = 'code'; const ATTRIBUTE_PICKUP_ADDRESS = 'address'; + const ATTRIBUTE_CUSTOMS = 'customs'; const RELATIONSHIP_CONTRACT = 'contract'; const RELATIONSHIP_FILES = 'files'; @@ -52,6 +54,7 @@ class Shipment implements ShipmentInterface self::ATTRIBUTE_RECIPIENT_ADDRESS => null, self::ATTRIBUTE_SENDER_ADDRESS => null, self::ATTRIBUTE_PICKUP => null, + self::ATTRIBUTE_CUSTOMS => null, ]; private $relationships = [ self::RELATIONSHIP_SHOP => [ @@ -290,7 +293,7 @@ public function setWeight($weight, $unit = self::WEIGHT_GRAM) throw new MyParcelComException('invalid unit: ' . $unit); } - $this->attributes[self::ATTRIBUTE_WEIGHT] = round($weight * self::$unitConversion[$unit]); + $this->attributes[self::ATTRIBUTE_WEIGHT] = (int)round($weight * self::$unitConversion[$unit]); return $this; } @@ -304,7 +307,7 @@ public function getWeight($unit = self::WEIGHT_GRAM) throw new MyParcelComException('invalid unit: ' . $unit); } - return round($this->attributes[self::ATTRIBUTE_WEIGHT] / self::$unitConversion[$unit]); + return (int)round($this->attributes[self::ATTRIBUTE_WEIGHT] / self::$unitConversion[$unit]); } /** @@ -466,4 +469,22 @@ public function getContract() { return $this->relationships[self::RELATIONSHIP_CONTRACT]['data']; } + + /** + * {@inheritdoc} + */ + public function setCustoms(CustomsInterface $customs) + { + $this->attributes[self::ATTRIBUTE_CUSTOMS] = $customs; + + return $this; + } + + /** + * {@inheritdoc} + */ + public function getCustoms() + { + return $this->attributes[self::ATTRIBUTE_CUSTOMS]; + } } From 972780d8c5db4ad7b943f414e51ac1b9cd691787 Mon Sep 17 00:00:00 2001 From: Shady Khattab Date: Mon, 4 Dec 2017 16:03:17 +0100 Subject: [PATCH 2/2] :white_check_mark: Created tests for customs and updated other tests --- tests/Feature/ResourceFactoryTest.php | 228 +++++++++++++++++- ...ttps---api-v1-shipments-shipment-id-1.json | 41 ++++ tests/Stubs/get/https---api-v1-shipments.json | 41 ++++ tests/Unit/CustomsItemTest.php | 86 +++++++ tests/Unit/CustomsTest.php | 110 +++++++++ tests/Unit/PositionTest.php | 20 ++ tests/Unit/ShipmentTest.php | 81 ++++++- 7 files changed, 602 insertions(+), 5 deletions(-) create mode 100644 tests/Unit/CustomsItemTest.php create mode 100644 tests/Unit/CustomsTest.php diff --git a/tests/Feature/ResourceFactoryTest.php b/tests/Feature/ResourceFactoryTest.php index 8b8000de..6205bb58 100644 --- a/tests/Feature/ResourceFactoryTest.php +++ b/tests/Feature/ResourceFactoryTest.php @@ -157,10 +157,6 @@ public function testCreateContract() ], $contract->jsonSerialize()); } - // TODO - const TYPE_FILE = 'files'; - - /** @test */ public function testCreateEmptyPickUpDropOffLocation() { @@ -624,6 +620,230 @@ public function testCreateShipment() ], $shipment->jsonSerialize()); } + /** @test */ + public function testCreateShipmentWitCustoms() + { + $resourceFactory = new ResourceFactory(); + $shipment = $resourceFactory->create('shipments', [ + 'barcode' => 'S3BARCODE', + 'description' => 'order #012ASD', + 'price' => 99, + 'currency' => 'USD', + 'insurance_amount' => 50, + 'weight' => 8000, + 'physical_properties' => [ + 'weight' => 1000, + 'length' => 1100, + 'volume' => 1200, + 'height' => 1300, + 'width' => 1400, + ], + 'recipient_address' => [ + 'street_1' => 'Diagonally', + 'street_2' => 'Apartment 4', + 'street_number' => '1', + 'street_number_suffix' => 'A', + 'postal_code' => '1AR BR2', + 'city' => 'London', + 'country_code' => 'GB', + 'first_name' => 'Robert', + 'last_name' => 'Drop Tables', + 'company' => 'ACME co.', + 'email' => 'rob@tables.com', + 'phone_number' => '+31 (0)234 567 890', + ], + 'sender_address' => [ + 'street_1' => 'Diagonally', + 'street_2' => 'Apartment 9', + 'street_number' => '4', + 'street_number_suffix' => 'A', + 'postal_code' => '1AR BR2', + 'city' => 'London', + 'country_code' => 'NL', + 'first_name' => 'Robert', + 'last_name' => 'Drop Tables', + 'company' => 'ACME co.', + 'email' => 'rob@tables.com', + 'phone_number' => '+31 (0)234 567 890', + ], + 'pickup_location_code' => 'CODE123', + 'pickup_location_address' => [ + 'street_1' => 'Diagonally', + 'street_2' => 'Apartment 41', + 'street_number' => '2', + 'street_number_suffix' => 'A', + 'postal_code' => '1AR BR2', + 'city' => 'London', + 'country_code' => 'GB', + 'first_name' => 'Robert', + 'last_name' => 'Drop Tables', + 'company' => 'ACME co.', + 'email' => 'rob@tables.com', + 'phone_number' => '+31 (0)234 567 890', + ], + 'customs' => [ + 'content_type' => 'documents', + 'invoice_number' => 'NO.5', + 'items' => [ + [ + 'sku' => '123456789', + 'description' => 'OnePlus X', + 'item_value' => 100, + 'currency' => 'GBP', + 'quantity' => 2, + 'hs_code' => '8517.12.00', + 'origin_country_code' => 'GB', + ], + [ + 'sku' => '213425', + 'description' => 'OnePlus One', + 'item_value' => 200, + 'currency' => 'GBP', + 'quantity' => 3, + 'hs_code' => '8517.12.00', + 'origin_country_code' => 'GB', + ], + [ + 'sku' => '6876', + 'description' => 'OnePlus Two', + 'item_value' => 300, + 'currency' => 'GBP', + 'quantity' => 1, + 'hs_code' => '8517.12.00', + 'origin_country_code' => 'GB', + ], + ], + 'non_delivery' => 'return', + 'incoterm' => 'DDU', + ], + 'shop' => ['id' => 'shop-id-1', 'type' => 'shops'], + 'service' => ['id' => 'service-id-1', 'type' => 'services'], + 'contract' => ['id' => 'contract-id-1', 'type' => 'contracts'], + 'status' => ['id' => 'status-id-1', 'type' => 'statuses'], + 'options' => [['id' => 'option-id-1', 'type' => 'service-options']], + 'files' => [['id' => 'file-id-1', 'type' => 'files']], + ]); + + $this->assertInstanceOf(ShipmentInterface::class, $shipment); + $this->assertEquals([ + 'type' => 'shipments', + 'attributes' => [ + 'barcode' => 'S3BARCODE', + 'description' => 'order #012ASD', + 'price' => [ + 'amount' => 99, + 'currency' => 'USD', + ], + 'insurance' => [ + 'amount' => 50, + 'currency' => 'USD', + ], + 'weight' => 8000, + 'physical_properties' => [ + 'weight' => 1000, + 'length' => 1100, + 'volume' => 1200, + 'height' => 1300, + 'width' => 1400, + ], + 'recipient_address' => [ + 'street_1' => 'Diagonally', + 'street_2' => 'Apartment 4', + 'street_number' => '1', + 'street_number_suffix' => 'A', + 'postal_code' => '1AR BR2', + 'city' => 'London', + 'country_code' => 'GB', + 'first_name' => 'Robert', + 'last_name' => 'Drop Tables', + 'company' => 'ACME co.', + 'email' => 'rob@tables.com', + 'phone_number' => '+31 (0)234 567 890', + ], + 'sender_address' => [ + 'street_1' => 'Diagonally', + 'street_2' => 'Apartment 9', + 'street_number' => '4', + 'street_number_suffix' => 'A', + 'postal_code' => '1AR BR2', + 'city' => 'London', + 'country_code' => 'NL', + 'first_name' => 'Robert', + 'last_name' => 'Drop Tables', + 'company' => 'ACME co.', + 'email' => 'rob@tables.com', + 'phone_number' => '+31 (0)234 567 890', + ], + 'pickup_location' => [ + 'code' => 'CODE123', + 'address' => [ + 'street_1' => 'Diagonally', + 'street_2' => 'Apartment 41', + 'street_number' => '2', + 'street_number_suffix' => 'A', + 'postal_code' => '1AR BR2', + 'city' => 'London', + 'country_code' => 'GB', + 'first_name' => 'Robert', + 'last_name' => 'Drop Tables', + 'company' => 'ACME co.', + 'email' => 'rob@tables.com', + 'phone_number' => '+31 (0)234 567 890', + ], + ], + 'customs' => [ + 'content_type' => 'documents', + 'invoice_number' => 'NO.5', + 'items' => [ + [ + 'sku' => '123456789', + 'description' => 'OnePlus X', + 'item_value' => [ + 'amount' => 100, + 'currency' => 'GBP', + ], + 'quantity' => 2, + 'hs_code' => '8517.12.00', + 'origin_country_code' => 'GB', + ], + [ + 'sku' => '213425', + 'description' => 'OnePlus One', + 'item_value' => [ + 'amount' => 200, + 'currency' => 'GBP', + ], + 'quantity' => 3, + 'hs_code' => '8517.12.00', + 'origin_country_code' => 'GB', + ], + [ + 'sku' => '6876', + 'description' => 'OnePlus Two', + 'item_value' => [ + 'amount' => 300, + 'currency' => 'GBP', + ], + 'quantity' => 1, + 'hs_code' => '8517.12.00', + 'origin_country_code' => 'GB', + ], + ], + 'non_delivery' => 'return', + 'incoterm' => 'DDU', + ], + ], + 'relationships' => [ + 'shop' => ['data' => ['id' => 'shop-id-1', 'type' => 'shops']], + 'service' => ['data' => ['id' => 'service-id-1', 'type' => 'services']], + 'contract' => ['data' => ['id' => 'contract-id-1', 'type' => 'contracts']], + 'status' => ['data' => ['id' => 'status-id-1', 'type' => 'statuses']], + 'options' => ['data' => [['id' => 'option-id-1', 'type' => 'service-options']]], + 'files' => ['data' => [['id' => 'file-id-1', 'type' => 'files']]], + ], + ], $shipment->jsonSerialize()); + } + /** @test */ public function testCreateEmptyShop() { diff --git a/tests/Stubs/get/https---api-v1-shipments-shipment-id-1.json b/tests/Stubs/get/https---api-v1-shipments-shipment-id-1.json index 001c1f02..e48acc53 100644 --- a/tests/Stubs/get/https---api-v1-shipments-shipment-id-1.json +++ b/tests/Stubs/get/https---api-v1-shipments-shipment-id-1.json @@ -69,6 +69,47 @@ "volume": 50, "weight": 24 }, + "customs": { + "content_type": "documents", + "invoice_number": "NO.5", + "items": [ + { + "sku": "123456789", + "description": "OnePlus X", + "item_value": { + "amount": 100, + "currency": "GBP" + }, + "quantity": 2, + "hs_code": "8517.12.00", + "origin_country_code": "GB" + }, + { + "sku": "213425", + "description": "OnePlus One", + "item_value": { + "amount": 200, + "currency": "GBP" + }, + "quantity": 3, + "hs_code": "8517.12.00", + "origin_country_code": "GB" + }, + { + "sku": "6876", + "description": "OnePlus Two", + "item_value": { + "amount": 300, + "currency": "GBP" + }, + "quantity": 1, + "hs_code": "8517.12.00", + "origin_country_code": "GB" + } + ], + "non_delivery": "return", + "incoterm": "DDU" + }, "created_at": 1504801719, "updated_at": 1504801719, "synced_at": 1504801719 diff --git a/tests/Stubs/get/https---api-v1-shipments.json b/tests/Stubs/get/https---api-v1-shipments.json index 998e212c..0220e13e 100644 --- a/tests/Stubs/get/https---api-v1-shipments.json +++ b/tests/Stubs/get/https---api-v1-shipments.json @@ -52,6 +52,47 @@ "phone_number": "+31 234 567 890" } }, + "customs": { + "content_type": "documents", + "invoice_number": "NO.5", + "items": [ + { + "sku": "123456789", + "description": "OnePlus X", + "item_value": { + "amount": 100, + "currency": "GBP" + }, + "quantity": 2, + "hs_code": "8517.12.00", + "origin_country_code": "GB" + }, + { + "sku": "213425", + "description": "OnePlus One", + "item_value": { + "amount": 200, + "currency": "GBP" + }, + "quantity": 3, + "hs_code": "8517.12.00", + "origin_country_code": "GB" + }, + { + "sku": "6876", + "description": "OnePlus Two", + "item_value": { + "amount": 300, + "currency": "GBP" + }, + "quantity": 1, + "hs_code": "8517.12.00", + "origin_country_code": "GB" + } + ], + "non_delivery": "return", + "incoterm": "DDU" + }, "description": "order #8008135", "price": { "amount": 100, diff --git a/tests/Unit/CustomsItemTest.php b/tests/Unit/CustomsItemTest.php new file mode 100644 index 00000000..24c53bc7 --- /dev/null +++ b/tests/Unit/CustomsItemTest.php @@ -0,0 +1,86 @@ +assertEquals('CM01-W', $item->setSku('CM01-W')->getSku()); + } + + /** @test */ + public function testDescription() + { + $item = new CustomsItem(); + $this->assertEquals('Tea cup', $item->setDescription('Tea cup')->getDescription()); + } + + /** @test */ + public function testHsCode() + { + $item = new CustomsItem(); + $this->assertEquals('8321.21.28', $item->setHsCode('8321.21.28')->getHsCode()); + } + + /** @test */ + public function testQuantity() + { + $item = new CustomsItem(); + $this->assertEquals(12, $item->setQuantity(12)->getQuantity()); + } + + /** @test */ + public function testItemValue() + { + $item = new CustomsItem(); + $this->assertEquals(349, $item->setItemValue(349)->getItemValue()); + } + + /** @test */ + public function testCurrency() + { + $item = new CustomsItem(); + $this->assertEquals('GBP', $item->setCurrency('GBP')->getCurrency()); + } + + /** @test */ + public function testOriginCountryCode() + { + $item = new CustomsItem(); + $this->assertEquals('GB', $item->setOriginCountryCode('GB')->getOriginCountryCode()); + } + + /** @test */ + public function testJsonSerialize() + { + $item = (new CustomsItem()) + ->setSku('CM01-W') + ->setDescription('Tea cup') + ->setHsCode('8321.21.28') + ->setQuantity(12) + ->setItemValue(349) + ->setCurrency('GBP') + ->setOriginCountryCode('GB'); + $this->assertEquals( + [ + 'sku' => 'CM01-W', + 'description' => 'Tea cup', + 'hs_code' => '8321.21.28', + 'quantity' => 12, + 'item_value' => [ + 'amount' => 349, + 'currency' => 'GBP', + ], + 'origin_country_code' => 'GB', + + ], + $item->jsonSerialize() + ); + } +} diff --git a/tests/Unit/CustomsTest.php b/tests/Unit/CustomsTest.php new file mode 100644 index 00000000..7913318d --- /dev/null +++ b/tests/Unit/CustomsTest.php @@ -0,0 +1,110 @@ +assertEquals(CustomsInterface::CONTENT_TYPE_GIFTS, $customs->setContentType(CustomsInterface::CONTENT_TYPE_GIFTS)->getContentType()); + } + + /** @test */ + public function testInvoiceNumber() + { + $customs = new Customs(); + $this->assertEquals('Invoice#007', $customs->setInvoiceNumber('Invoice#007')->getInvoiceNumber()); + } + + /** @test */ + public function testItems() + { + $customs = new Customs(); + + $this->assertEmpty($customs->getItems()); + + $mock = $this->getMockClass(CustomsItemInterface::class); + $items = [new $mock(), new $mock()]; + + $customs->setItems($items); + $this->assertCount(2, $customs->getItems()); + $this->assertEquals($items, $customs->getItems()); + + $item = new $mock(); + $items[] = $item; + $customs->addItem($item); + $this->assertCount(3, $customs->getItems()); + $this->assertEquals($items, $customs->getItems()); + } + + /** @test */ + public function testNonDelivery() + { + $customs = new Customs(); + $this->assertEquals(CustomsInterface::NON_DELIVERY_ABANDON, $customs->setNonDelivery(CustomsInterface::NON_DELIVERY_ABANDON)->getNonDelivery()); + } + + /** @test */ + public function testIncoterm() + { + $customs = new Customs(); + $this->assertEquals(CustomsInterface::INCOTERM_DDP, $customs->setIncoterm(CustomsInterface::INCOTERM_DDP)->getIncoterm()); + } + + /** @test */ + public function testJsonSerialize() + { + $item = $this->getMockBuilder(CustomsItemInterface::class) + ->disableOriginalConstructor() + ->disableOriginalClone() + ->disableArgumentCloning() + ->disallowMockingUnknownTypes() + ->getMock(); + $item->method('jsonSerialize') + ->willReturn([ + 'sku' => '123456789', + 'description' => 'OnePlus X', + 'item_value' => [ + 'amount' => 100, + 'currency' => 'EUR', + ], + 'quantity' => 2, + 'hs_code' => '8517.12.00', + 'origin_country_code' => 'GB', + ]); + + $customs = (new Customs()) + ->setItems([$item]) + ->setIncoterm(CustomsInterface::INCOTERM_DDU) + ->setNonDelivery(CustomsInterface::NON_DELIVERY_RETURN) + ->setInvoiceNumber('NO.5') + ->setContentType(CustomsInterface::CONTENT_TYPE_DOCUMENTS); + + $this->assertEquals([ + 'content_type' => 'documents', + 'invoice_number' => 'NO.5', + 'items' => [ + [ + 'sku' => '123456789', + 'description' => 'OnePlus X', + 'item_value' => [ + 'amount' => 100, + 'currency' => 'EUR', + ], + 'quantity' => 2, + 'hs_code' => '8517.12.00', + 'origin_country_code' => 'GB', + ], + ], + 'non_delivery' => 'return', + 'incoterm' => 'DDU', + ], $customs->jsonSerialize()); + } +} diff --git a/tests/Unit/PositionTest.php b/tests/Unit/PositionTest.php index 68522539..fdeef17f 100644 --- a/tests/Unit/PositionTest.php +++ b/tests/Unit/PositionTest.php @@ -3,6 +3,7 @@ namespace MyParcelCom\Sdk\Tests\Unit; use MyParcelCom\Sdk\Resources\Position; +use MyParcelCom\Sdk\Exceptions\MyParcelComException; use PHPUnit\Framework\TestCase; class PositionTest extends TestCase @@ -36,6 +37,25 @@ public function testDistance() $this->assertEquals(12, $position->setDistance(19312)->getDistance(Position::UNIT_MILE)); } + /** @test */ + public function testSetDistanceInvalidUnit() + { + $position = new Position(); + + $this->expectException(MyParcelComException::class); + $position->setDistance(900, 'lightyears'); + } + + /** @test */ + public function testGetDistanceInvalidUnit() + { + $position = new Position(); + $position->setDistance(900); + + $this->expectException(MyParcelComException::class); + $position->getDistance('au'); + } + /** @test */ public function testJsonSerialize() { diff --git a/tests/Unit/ShipmentTest.php b/tests/Unit/ShipmentTest.php index c1c1fa42..79eec273 100644 --- a/tests/Unit/ShipmentTest.php +++ b/tests/Unit/ShipmentTest.php @@ -2,8 +2,10 @@ namespace MyParcelCom\Sdk\Tests\Unit; +use MyParcelCom\Sdk\Exceptions\MyParcelComException; use MyParcelCom\Sdk\Resources\Interfaces\AddressInterface; use MyParcelCom\Sdk\Resources\Interfaces\ContractInterface; +use MyParcelCom\Sdk\Resources\Interfaces\CustomsInterface; use MyParcelCom\Sdk\Resources\Interfaces\FileInterface; use MyParcelCom\Sdk\Resources\Interfaces\PhysicalPropertiesInterface; use MyParcelCom\Sdk\Resources\Interfaces\ServiceInterface; @@ -121,6 +123,25 @@ public function testWeight() $this->assertEquals(2, $shipment->setWeight(12701)->getWeight(Shipment::WEIGHT_STONE)); } + /** @test */ + public function testSetWeightInvalidUnit() + { + $shipment = new Shipment(); + + $this->expectException(MyParcelComException::class); + $shipment->setWeight(8000, 'tons'); + } + + /** @test */ + public function testGetWeightInvalidUnit() + { + $shipment = new Shipment(); + $shipment->setWeight(8000); + + $this->expectException(MyParcelComException::class); + $shipment->getWeight('truckloads'); + } + /** @test */ public function testPhysicalProperties() { @@ -191,6 +212,17 @@ public function testStatus() $this->assertEquals($status, $shipment->setStatus($status)->getStatus()); } + /** @test */ + public function testCustoms() + { + $shipment = new Shipment(); + + $mock = $this->getMockClass(CustomsInterface::class); + $customs = new $mock(); + + $this->assertEquals($customs, $shipment->setCustoms($customs)->getCustoms()); + } + /** @test */ public function testFiles() { @@ -408,6 +440,33 @@ public function testJsonSerialize() 'type' => 'statuses', ]); + $customs = $this->getMockBuilder(CustomsInterface::class) + ->disableOriginalConstructor() + ->disableOriginalClone() + ->disableArgumentCloning() + ->disallowMockingUnknownTypes() + ->getMock(); + $customs->method('jsonSerialize') + ->willReturn([ + 'content_type' => 'documents', + 'invoice_number' => 'NO.5', + 'items' => [ + [ + 'sku' => '123456789', + 'description' => 'OnePlus X', + 'item_value' => [ + 'amount' => 100, + 'currency' => 'EUR', + ], + 'quantity' => 2, + 'hs_code' => '8517.12.00', + 'origin_country_code' => 'GB', + ], + ], + 'non_delivery' => 'return', + 'incoterm' => 'DDU', + ]); + $shipment = (new Shipment()) ->setId('shipment-id') ->setDescription('order #012ASD') @@ -426,7 +485,8 @@ public function testJsonSerialize() ->setStatus($status) ->setRecipientAddress($recipientAddress) ->setSenderAddress($senderAddress) - ->setPickupLocationAddress($pudoAddress); + ->setPickupLocationAddress($pudoAddress) + ->setCustoms($customs); $this->assertEquals([ 'id' => 'shipment-id', @@ -498,6 +558,25 @@ public function testJsonSerialize() 'phone_number' => '+31 (0)234 567 890', ], ], + 'customs' => [ + 'content_type' => 'documents', + 'invoice_number' => 'NO.5', + 'items' => [ + [ + 'sku' => '123456789', + 'description' => 'OnePlus X', + 'item_value' => [ + 'amount' => 100, + 'currency' => 'EUR', + ], + 'quantity' => 2, + 'hs_code' => '8517.12.00', + 'origin_country_code' => 'GB', + ], + ], + 'non_delivery' => 'return', + 'incoterm' => 'DDU', + ], ], 'relationships' => [ 'shop' => ['data' => ['id' => 'shop-id-1', 'type' => 'shops']],