From 73efb7c1833ef2b8858a99987590010d952e33c2 Mon Sep 17 00:00:00 2001 From: jacobdekeizer Date: Mon, 22 Jun 2026 20:31:57 +0200 Subject: [PATCH 1/7] V3 --- .ddev/config.yaml | 12 + .gitattributes | 4 + .gitignore | 2 +- CHANGELOG.md | 77 ++++++ composer.json | 2 +- composer.lock | 20 -- src/Client.php | 93 ++----- src/Contracts/Dto.php | 7 - src/Dto/Session.php | 4 - src/Endpoints/BaseEndpoint.php | 47 +--- src/Endpoints/LabelsEndpoint.php | 9 +- src/Endpoints/SessionEndpoint.php | 7 +- src/Endpoints/ShipmentsEndpoint.php | 163 ++++++++++-- src/Endpoints/WmsEndpoint.php | 81 ++++++ src/Enums/CountryCode.php | 1 + src/Enums/ResponseCode.php | 7 +- src/Resources/AddShipmentRowResponse.php | 133 ++++++++++ src/Resources/Address.php | 2 +- src/Resources/AdrData.php | 210 +++++++++++++++ src/Resources/BarcodeData.php | 22 ++ src/Resources/DeleteShipmentResponse.php | 47 +--- src/Resources/DeleteShipmentRowResponse.php | 40 +++ src/Resources/EtaResponse.php | 67 ++--- src/Resources/LabelResponse.php | 102 ++++---- src/Resources/PhotoData.php | 79 ++++++ src/Resources/PhotoResponse.php | 67 +++++ src/Resources/PodResponse.php | 92 +++++++ src/Resources/SendShipmentResponse.php | 62 ++--- src/Resources/SendShipmentsResponse.php | 49 ++-- src/Resources/ShipmentInfoResponse.php | 247 ++++++++++++++++++ src/Resources/ShipmentResponse.php | 140 ++++++---- src/Resources/ShipmentRow.php | 201 +++++--------- src/Resources/ShipmentTypeTableItem.php | 48 ++++ src/Resources/StatusDataResponse.php | 155 +++-------- src/Resources/StatusResponse.php | 67 +++-- src/Resources/StatusTableItem.php | 48 ++++ src/Resources/StatusweblinkResponse.php | 53 ++++ src/Resources/Wms/ArticleData.php | 32 +++ src/Resources/Wms/DeleteDeliveryResponse.php | 13 + src/Resources/Wms/DeliveryRequest.php | 159 +++++++++++ src/Resources/Wms/DeliveryRequestResponse.php | 27 ++ src/Resources/Wms/DeliveryStatusItem.php | 79 ++++++ src/Resources/Wms/DeliveryStatusResponse.php | 40 +++ src/Resources/Wms/InventoryItem.php | 53 ++++ src/Resources/Wms/InventoryResponse.php | 40 +++ 45 files changed, 2221 insertions(+), 689 deletions(-) create mode 100644 .ddev/config.yaml create mode 100644 .gitattributes create mode 100644 CHANGELOG.md delete mode 100644 composer.lock create mode 100644 src/Endpoints/WmsEndpoint.php create mode 100644 src/Resources/AddShipmentRowResponse.php create mode 100644 src/Resources/AdrData.php create mode 100644 src/Resources/BarcodeData.php create mode 100644 src/Resources/DeleteShipmentRowResponse.php create mode 100644 src/Resources/PhotoData.php create mode 100644 src/Resources/PhotoResponse.php create mode 100644 src/Resources/PodResponse.php create mode 100644 src/Resources/ShipmentInfoResponse.php create mode 100644 src/Resources/ShipmentTypeTableItem.php create mode 100644 src/Resources/StatusTableItem.php create mode 100644 src/Resources/StatusweblinkResponse.php create mode 100644 src/Resources/Wms/ArticleData.php create mode 100644 src/Resources/Wms/DeleteDeliveryResponse.php create mode 100644 src/Resources/Wms/DeliveryRequest.php create mode 100644 src/Resources/Wms/DeliveryRequestResponse.php create mode 100644 src/Resources/Wms/DeliveryStatusItem.php create mode 100644 src/Resources/Wms/DeliveryStatusResponse.php create mode 100644 src/Resources/Wms/InventoryItem.php create mode 100644 src/Resources/Wms/InventoryResponse.php diff --git a/.ddev/config.yaml b/.ddev/config.yaml new file mode 100644 index 0000000..4fe2ae4 --- /dev/null +++ b/.ddev/config.yaml @@ -0,0 +1,12 @@ +name: statusweb-client +type: php +docroot: "" +php_version: "8.5" +webserver_type: generic +xdebug_enabled: false +additional_hostnames: [] +additional_fqdns: [] +use_dns_when_possible: true +composer_version: "2" +web_environment: [] +corepack_enable: false diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..199dd23 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,4 @@ +.gitattributes export-ignore +.gitignore export-ignore +.ddev export-ignore +CHANGELOG.md export-ignore \ No newline at end of file diff --git a/.gitignore b/.gitignore index ccad85d..4f38912 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,3 @@ .idea vendor -test.php +composer.lock diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..b18ce65 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,77 @@ +# Changelog + +## [v3.0.0] - 2026-06-22 + +### Breaking changes +- PHP requirement raised to `>=8.5` +- Statusweb SOAP API upgraded from v4 to v6 +- All `Vrachtnummer` parameters and response fields renamed to `Zendingnummer` (shipment number) +- `Address::toRequest()` field `Huisnr` renamed to `Huisnummer` (matches v6 API) +- `ShipmentsEndpoint::getStatus()` parameter changed from `float` to `int` +- `ShipmentsEndpoint::delete()` parameter changed from `float` to `int` +- `ShipmentsEndpoint::getStatusUrl()` now returns `StatusweblinkResponse` instead of `string` +- `ShipmentsEndpoint::getAllStatuses()` now accepts optional `?string $mark` parameter for pagination and returns `StatusResponse` with `mark` and `more` fields +- `LabelsEndpoint::get()` parameter changed from `float` to `int` +- `SendShipmentsResponse::getSendShipmentData()` renamed to `getShipments()` +- `StatusDataResponse::getTransportNumber()` renamed to `getShipmentNumber()` +- `ShipmentResponse::getTransportNumber()` renamed to `getShipmentNumber()` +- `DeleteShipmentResponse::getTransportNumber()` renamed to `getShipmentNumber()` +- `SendShipmentResponse::getTransportNumber()` renamed to `getShipmentNumber()` +- `LabelResponse::getTransportNumber()` renamed to `getShipmentNumber()` +- `ResponseCode::COUNTRY_CODE_INVALID` split into `COUNTRY_CODE_DELIVERY_INVALID` (-105) and `COUNTRY_CODE_LOADING_INVALID` (-111) +- `ResponseCode::NO_ETA_FOR_SHIPMENT` corrected from -320 to -400 +- `ResponseCode::UNKNOWN_RESULT_ID` renamed to `DELIVERY_REQUEST_NOT_FOUND` (-550) + +### New features + +#### TMS — new endpoint methods on `$client->shipments()` +- `addShipmentRow(int $shipmentNumber, ShipmentRow $row, LabelData $labelData): AddShipmentRowResponse` +- `deleteShipmentRow(int $shipmentNumber, int $rowId): DeleteShipmentRowResponse` +- `sendShipment(int $shipmentNumber): SendShipmentsResponse` +- `getInfo(int $shipmentNumber): ZendingInfoResponse` +- `getInfoSend(int $shipmentNumber): ZendingInfoResponse` +- `getPod(int $shipmentNumber): PodResponse` +- `getPhotos(int $shipmentNumber): FotoResponse` +- `getStatusTable(): StatusTableItem[]` +- `getShipmentTypeTable(): ShipmentTypeTableItem[]` + +#### WMS — new endpoint `$client->wms()` +- `getInventory(): InventoryResponse` +- `getArticleInventory(string $articleNumber): InventoryResponse` +- `createDeliveryRequest(DeliveryRequest $request): DeliveryRequestResponse` +- `deleteDeliveryRequest(int $deliveryId): DeleteDeliveryResponse` +- `getDeliveryRequestStatus(int $deliveryId): DeliveryStatusResponse` +- `getShipmentsByDeliveryRequest(int $deliveryId): SendShipmentsResponse` + +#### New resource classes +- `AdrData` — ADR (hazardous goods) request data for shipment rows +- `BarcodeData` — barcode request/response data +- `AddShipmentRowResponse` +- `DeleteShipmentRowResponse` +- `StatusweblinkResponse` +- `ShipmentInfoResponse` — full shipment detail response +- `PodResponse` — proof of delivery response +- `PhotoData`, `PhotoResponse` — delivery photo response +- `StatusTableItem`, `ShipmentTypeTableItem` — table lookup responses +- `Wms\ArticleData`, `Wms\DeliveryRequest` +- `Wms\InventoryItem`, `Wms\InventoryResponse` +- `Wms\DeliveryRequestResponse`, `Wms\DeleteDeliveryResponse` +- `Wms\DeliveryStatusItem`, `Wms\DeliveryStatusResponse` + +#### Enhancements to existing resources +- `ShipmentRow` — added `Barcodes` and `ADR` fields +- `ShipmentResponse` — added `statuswebLink`, `labelLength`, `barcodes`, `rowIds` +- `SendShipmentResponse` — added `statuswebLink` +- `LabelResponse` — added `labelLength`, `barcodes` +- `EtaResponse` — added `shipmentNumber`, `reference` +- `StatusResponse` — added `mark`, `hasMore` for paginated `GetStatus` polling +- `CountryCode` — added `LUXEMBOURG = 352` + +--- + +## [v2.0.0] + +- Statusweb SOAP API v4 +- TMS functions: create, delete, send, getStatus, getAllStatuses, getStatusUrl, getEstimatedTimeOfArrival +- Labels endpoint: get label by shipment number +- Session management with configurable session store diff --git a/composer.json b/composer.json index 32a48e9..6f14af5 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,7 @@ } ], "require": { - "php": ">=7.2", + "php": ">=8.5", "ext-soap": "*", "ext-json": "*" }, diff --git a/composer.lock b/composer.lock deleted file mode 100644 index d5e24ca..0000000 --- a/composer.lock +++ /dev/null @@ -1,20 +0,0 @@ -{ - "_readme": [ - "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", - "This file is @generated automatically" - ], - "content-hash": "6e8f861361e30d15f2498d8c311d5aba", - "packages": [], - "packages-dev": [], - "aliases": [], - "minimum-stability": "stable", - "stability-flags": [], - "prefer-stable": false, - "prefer-lowest": false, - "platform": { - "php": ">=7.2", - "ext-soap": "*" - }, - "platform-dev": [] -} diff --git a/src/Client.php b/src/Client.php index 6493d0e..feae8d7 100644 --- a/src/Client.php +++ b/src/Client.php @@ -9,42 +9,16 @@ class Client { - public const SOAP_DOCUMENT = 'https://www.statusweb.nl/StatuswebAPIv4/Service.wso?WSDL'; - - /** - * @var SoapClient - */ - private $soapClient; - - /** - * @var SessionStore - */ - private $sessionStore; - - /** - * @var Endpoints\SessionEndpoint - */ - private $sessionEndpoint; - - /** - * @var Endpoints\ShipmentsEndpoint - */ - private $shipmentsEndpoint; - - /** - * @var Endpoints\LabelsEndpoint - */ - private $labelsEndpoint; - - /** - * @var string - */ - private $apiKey; - - /** - * @var string - */ - private $password; + public const SOAP_DOCUMENT = 'https://www.statusweb.nl/StatuswebAPIv6/Service.wso?WSDL'; + + private SoapClient $soapClient; + private SessionStore $sessionStore; + private Endpoints\SessionEndpoint $sessionEndpoint; + private Endpoints\ShipmentsEndpoint $shipmentsEndpoint; + private Endpoints\LabelsEndpoint $labelsEndpoint; + private Endpoints\WmsEndpoint $wmsEndpoint; + private string $apiKey; + private string $password; public function __construct() { @@ -53,91 +27,64 @@ public function __construct() $this->sessionEndpoint = new Endpoints\SessionEndpoint($this); $this->shipmentsEndpoint = new Endpoints\ShipmentsEndpoint($this); $this->labelsEndpoint = new Endpoints\LabelsEndpoint($this); + $this->wmsEndpoint = new Endpoints\WmsEndpoint($this); } - /** - * @param string $apiKey - * @return Client - */ - public function setApiKey(string $apiKey): Client + public function setApiKey(string $apiKey): static { $this->apiKey = $apiKey; return $this; } - /** - * @return string - */ public function getApiKey(): string { return $this->apiKey; } - /** - * @param string $password - * @return Client - */ - public function setPassword(string $password): Client + public function setPassword(string $password): static { $this->password = $password; return $this; } - /** - * @return string - */ public function getPassword(): string { return $this->password; } - /** - * @param SessionStore $sessionStore - * @return Client - */ - public function setSessionStore(SessionStore $sessionStore): Client + public function setSessionStore(SessionStore $sessionStore): static { $this->sessionStore = $sessionStore; return $this; } - /** - * @return SessionStore - */ public function getSessionStore(): SessionStore { return $this->sessionStore; } - /** - * @return Endpoints\ShipmentsEndpoint - */ public function shipments(): Endpoints\ShipmentsEndpoint { return $this->shipmentsEndpoint; } - /** - * @return Endpoints\LabelsEndpoint - */ public function labels(): Endpoints\LabelsEndpoint { return $this->labelsEndpoint; } - /** - * @return Endpoints\SessionEndpoint - */ public function session(): Endpoints\SessionEndpoint { return $this->sessionEndpoint; } - /** - * @return SoapClient - */ + public function wms(): Endpoints\WmsEndpoint + { + return $this->wmsEndpoint; + } + public function soap(): SoapClient { return $this->soapClient; } -} \ No newline at end of file +} diff --git a/src/Contracts/Dto.php b/src/Contracts/Dto.php index c15ae90..d62e40c 100644 --- a/src/Contracts/Dto.php +++ b/src/Contracts/Dto.php @@ -4,14 +4,7 @@ interface Dto { - /** - * @return array - */ public function toArray(): array; - /** - * @param array $data - * @return Dto - */ public static function fromArray(array $data): Dto; } \ No newline at end of file diff --git a/src/Dto/Session.php b/src/Dto/Session.php index f8905f3..7a28d19 100644 --- a/src/Dto/Session.php +++ b/src/Dto/Session.php @@ -63,10 +63,6 @@ public function toArray(): array ]; } - /** - * @inheritDoc - * @return Session - */ public static function fromArray(array $data): Dto { return (new self) diff --git a/src/Endpoints/BaseEndpoint.php b/src/Endpoints/BaseEndpoint.php index 70ab83b..2148f21 100644 --- a/src/Endpoints/BaseEndpoint.php +++ b/src/Endpoints/BaseEndpoint.php @@ -12,27 +12,10 @@ abstract class BaseEndpoint { - /** - * @var Client - */ - protected $client; - - /** - * @param Client $client - */ - public function __construct(Client $client) + public function __construct(protected Client $client) { - $this->client = $client; } - /** - * @param string $endpoint - * @param array $data - * @param bool $authentication - * @return array - * @throws StatuswebException - * @throws StatuswebErrorResponse - */ protected function doRequest(string $endpoint, array $data = [], bool $authentication = true): array { if ($authentication) { @@ -40,20 +23,12 @@ protected function doRequest(string $endpoint, array $data = [], bool $authentic } try { - // do request and convert response to array return json_decode(json_encode($this->client->soap()->$endpoint($data)), true); } catch (Throwable $throwable) { throw StatuswebException::fromPrevious('Error executing api call', $throwable); } } - /** - * @param string $key - * @param array $result - * @return array - * @throws StatuswebErrorResponse - * @throws StatuswebException - */ protected function validateAndExtractData(string $key, array $result): array { $data = $result[$key] ?? []; @@ -63,34 +38,24 @@ protected function validateAndExtractData(string $key, array $result): array return $data; } - /** - * @param array $data - * @throws StatuswebException - * @throws StatuswebErrorResponse - */ protected function validateResponse(array $data): void { - if (array_key_exists('Errorcode', $data) === false) { + if (array_key_exists('ErrorCode', $data) === false) { throw new StatuswebException('Invalid response: ' . json_encode($data)); } - if ($data['Errorcode'] !== ResponseCode::OK) { - throw StatuswebErrorResponse::fromCode($data['Errorcode'], $data['Errorstring'] ?? ''); + if ($data['ErrorCode'] !== ResponseCode::OK) { + throw StatuswebErrorResponse::fromCode($data['ErrorCode'], $data['ErrorString'] ?? ''); } } - /** - * @return string sessionId - * @throws StatuswebErrorResponse - * @throws StatuswebException - */ private function login(): string { $store = $this->client->getSessionStore(); $session = $store->get($this->client->getApiKey()); - if ($session === null || ($session !== null && new DateTime() > new DateTime($session->getExpirationDate()))) { + if ($session === null || new DateTime() > new DateTime($session->getExpirationDate())) { $sessionResponse = $this->client->session()->get(); $session = (new Session) @@ -102,4 +67,4 @@ private function login(): string return $session->getSessionId(); } -} \ No newline at end of file +} diff --git a/src/Endpoints/LabelsEndpoint.php b/src/Endpoints/LabelsEndpoint.php index da31b4e..3c6f6e7 100644 --- a/src/Endpoints/LabelsEndpoint.php +++ b/src/Endpoints/LabelsEndpoint.php @@ -9,19 +9,16 @@ class LabelsEndpoint extends BaseEndpoint { /** - * @param float $transportNumber - * @param int $labelFormat - * @return LabelResponse * @throws StatuswebErrorResponse * @throws StatuswebException */ - public function get(float $transportNumber, int $labelFormat): LabelResponse + public function get(int $shipmentNumber, int $labelFormat): LabelResponse { $result = $this->doRequest('GetLabel', [ - 'Vrachtnummer' => $transportNumber, + 'Zendingnummer' => $shipmentNumber, 'Formaat' => $labelFormat, ]); return LabelResponse::fromResponse($this->validateAndExtractData('GetLabelResult', $result)); } -} \ No newline at end of file +} diff --git a/src/Endpoints/SessionEndpoint.php b/src/Endpoints/SessionEndpoint.php index 612ea7a..e0d54dc 100644 --- a/src/Endpoints/SessionEndpoint.php +++ b/src/Endpoints/SessionEndpoint.php @@ -10,13 +10,12 @@ class SessionEndpoint extends BaseEndpoint { /** - * @return SessionResponse * @throws StatuswebErrorResponse * @throws StatuswebException */ public function get(): SessionResponse { - $result = $this->doRequest('GetSessionId', [ + $result = $this->doRequest('GetSessionID', [ 'ApiKey' => $this->client->getApiKey(), 'Wachtwoord' => $this->client->getPassword(), ], false); @@ -24,9 +23,9 @@ public function get(): SessionResponse $data = $this->validateAndExtractData('GetSessionIDResult', $result); $data['ExpirationDate'] = (new DateTime) - ->modify('+1 hour 55 minutes') // keep safe 5 minute margin + ->modify('+1 hour 55 minutes') ->format('Y-m-d H:i:s'); return SessionResponse::fromResponse($data); } -} \ No newline at end of file +} diff --git a/src/Endpoints/ShipmentsEndpoint.php b/src/Endpoints/ShipmentsEndpoint.php index 58bb3ba..8d6138d 100644 --- a/src/Endpoints/ShipmentsEndpoint.php +++ b/src/Endpoints/ShipmentsEndpoint.php @@ -2,21 +2,28 @@ namespace JacobDeKeizer\Statusweb\Endpoints; -use DateTime; use JacobDeKeizer\Statusweb\Exceptions\StatuswebErrorResponse; use JacobDeKeizer\Statusweb\Exceptions\StatuswebException; +use JacobDeKeizer\Statusweb\Resources\AddShipmentRowResponse; use JacobDeKeizer\Statusweb\Resources\DeleteShipmentResponse; +use JacobDeKeizer\Statusweb\Resources\DeleteShipmentRowResponse; use JacobDeKeizer\Statusweb\Resources\EtaResponse; +use JacobDeKeizer\Statusweb\Resources\PhotoResponse; +use JacobDeKeizer\Statusweb\Resources\LabelData; +use JacobDeKeizer\Statusweb\Resources\PodResponse; use JacobDeKeizer\Statusweb\Resources\SendShipmentsResponse; use JacobDeKeizer\Statusweb\Resources\Shipment; use JacobDeKeizer\Statusweb\Resources\ShipmentResponse; +use JacobDeKeizer\Statusweb\Resources\ShipmentRow; +use JacobDeKeizer\Statusweb\Resources\ShipmentTypeTableItem; use JacobDeKeizer\Statusweb\Resources\StatusResponse; +use JacobDeKeizer\Statusweb\Resources\StatusTableItem; +use JacobDeKeizer\Statusweb\Resources\StatusweblinkResponse; +use JacobDeKeizer\Statusweb\Resources\ShipmentInfoResponse; class ShipmentsEndpoint extends BaseEndpoint { /** - * @param Shipment $shipment - * @return ShipmentResponse * @throws StatuswebErrorResponse * @throws StatuswebException */ @@ -28,20 +35,46 @@ public function create(Shipment $shipment): ShipmentResponse } /** - * @param float $transportNumber - * @return DeleteShipmentResponse * @throws StatuswebErrorResponse * @throws StatuswebException */ - public function delete(float $transportNumber): DeleteShipmentResponse + public function addShipmentRow(int $shipmentNumber, ShipmentRow $row, LabelData $labelData): AddShipmentRowResponse { - $result = $this->doRequest('DeleteZending', ['Vrachtnummer' => $transportNumber]); + $result = $this->doRequest('AddZendingRegel', [ + 'Zendingnummer' => $shipmentNumber, + 'ZendingregelData' => $row->toRequest(), + 'LabelData' => $labelData->toRequest(), + ]); + + return AddShipmentRowResponse::fromResponse($this->validateAndExtractData('AddZendingRegelResult', $result)); + } + + /** + * @throws StatuswebErrorResponse + * @throws StatuswebException + */ + public function deleteShipmentRow(int $shipmentNumber, int $rowId): DeleteShipmentRowResponse + { + $result = $this->doRequest('DeleteZendingRegel', [ + 'Zendingnummer' => $shipmentNumber, + 'Regel_ID' => $rowId, + ]); + + return DeleteShipmentRowResponse::fromResponse($this->validateAndExtractData('DeleteZendingRegelResult', $result)); + } + + /** + * @throws StatuswebErrorResponse + * @throws StatuswebException + */ + public function delete(int $shipmentNumber): DeleteShipmentResponse + { + $result = $this->doRequest('DeleteZending', ['Zendingnummer' => $shipmentNumber]); return DeleteShipmentResponse::fromResponse($this->validateAndExtractData('DeleteZendingResult', $result)); } /** - * @return SendShipmentsResponse * @throws StatuswebErrorResponse * @throws StatuswebException */ @@ -53,55 +86,129 @@ public function send(): SendShipmentsResponse } /** - * @param float $transportNumber - * @return StatusResponse * @throws StatuswebErrorResponse * @throws StatuswebException */ - public function getStatus(float $transportNumber): StatusResponse + public function sendShipment(int $shipmentNumber): SendShipmentsResponse { - $result = $this->doRequest('GetStatusVrachtnummer', ['Vrachtnummer' => $transportNumber]); + $result = $this->doRequest('SendZending', ['Zendingnummer' => $shipmentNumber]); - return StatusResponse::fromResponse($this->validateAndExtractData('GetStatusVrachtnummerResult', $result)); + return SendShipmentsResponse::fromResponse($this->validateAndExtractData('SendZendingResult', $result)); } /** - * @return StatusResponse * @throws StatuswebErrorResponse * @throws StatuswebException */ - public function getAllStatuses(): StatusResponse + public function getStatus(int $shipmentNumber): StatusResponse { - $result = $this->doRequest('GetStatus', ['Mark' => (new DateTime)->format('Y-m-d H:i:s')]); + $result = $this->doRequest('GetStatusZending', ['Zendingnummer' => $shipmentNumber]); + + return StatusResponse::fromResponse($this->validateAndExtractData('GetStatusZendingResult', $result)); + } + + /** + * @throws StatuswebErrorResponse + * @throws StatuswebException + */ + public function getAllStatuses(?string $mark = null): StatusResponse + { + $result = $this->doRequest('GetStatus', ['Mark' => $mark ?? '']); return StatusResponse::fromResponse($this->validateAndExtractData('GetStatusResult', $result)); } /** - * @param float $transportNumber - * @return string * @throws StatuswebErrorResponse * @throws StatuswebException */ - public function getStatusUrl(float $transportNumber): string + public function getStatusUrl(int $shipmentNumber): StatusweblinkResponse { - $result = $this->doRequest('GetStatusweblinkVrachtnummer', ['Vrachtnummer' => $transportNumber]); + $result = $this->doRequest('GetStatusweblinkZending', ['Zendingnummer' => $shipmentNumber]); - $data = $this->validateAndExtractData('GetStatusweblinkVrachtnummerResult', $result); + return StatusweblinkResponse::fromResponse($this->validateAndExtractData('GetStatusweblinkZendingResult', $result)); + } + + /** + * @throws StatuswebErrorResponse + * @throws StatuswebException + */ + public function getEstimatedTimeOfArrival(int $shipmentNumber): EtaResponse + { + $result = $this->doRequest('GetETAZending', ['Zendingnummer' => $shipmentNumber]); - return $data['Statusweblink']; + return EtaResponse::fromResponse($this->validateAndExtractData('GetETAZendingResult', $result)); } /** - * @param float $transportNumber - * @return EtaResponse * @throws StatuswebErrorResponse * @throws StatuswebException */ - public function getEstimatedTimeOfArrival(float $transportNumber): EtaResponse + public function getInfo(int $shipmentNumber): ShipmentInfoResponse { - $result = $this->doRequest('GetETAVrachtnummer', ['Vrachtnummer' => $transportNumber]); + $result = $this->doRequest('GetZendingInfo', ['Zendingnummer' => $shipmentNumber]); + + return ShipmentInfoResponse::fromResponse($this->validateAndExtractData('GetZendingInfoResult', $result)); + } + + /** + * @throws StatuswebErrorResponse + * @throws StatuswebException + */ + public function getInfoSend(int $shipmentNumber): ShipmentInfoResponse + { + $result = $this->doRequest('GetZendingInfoSend', ['Zendingnummer' => $shipmentNumber]); + + return ShipmentInfoResponse::fromResponse($this->validateAndExtractData('GetZendingInfoSendResult', $result)); + } + + /** + * @throws StatuswebErrorResponse + * @throws StatuswebException + */ + public function getPod(int $shipmentNumber): PodResponse + { + $result = $this->doRequest('GetPODZending', ['Zendingnummer' => $shipmentNumber]); + + return PodResponse::fromResponse($this->validateAndExtractData('GetPODZendingResult', $result)); + } + + /** + * @throws StatuswebErrorResponse + * @throws StatuswebException + */ + public function getPhotos(int $shipmentNumber): PhotoResponse + { + $result = $this->doRequest('GetFotoZending', ['Zendingnummer' => $shipmentNumber]); + + return PhotoResponse::fromResponse($this->validateAndExtractData('GetFotoZendingResult', $result)); + } + + /** + * @return StatusTableItem[] + * @throws StatuswebErrorResponse + * @throws StatuswebException + */ + public function getStatusTable(): array + { + $result = $this->doRequest('GetStatusTabel'); + + $data = $this->validateAndExtractData('GetStatusTabelResult', $result); + + return StatusTableItem::collectionFromResponse($data['StatusTabel']['StatusTabelData'] ?? []); + } + + /** + * @return ShipmentTypeTableItem[] + * @throws StatuswebErrorResponse + * @throws StatuswebException + */ + public function getShipmentTypeTable(): array + { + $result = $this->doRequest('GetZendingsoortTabel'); + + $data = $this->validateAndExtractData('GetZendingsoortTabelResult', $result); - return EtaResponse::fromResponse($this->validateAndExtractData('GetETAVrachtnummerResult', $result)); + return ShipmentTypeTableItem::collectionFromResponse($data['ZendingsoortTabel']['ZendingsoortTabelData'] ?? []); } -} \ No newline at end of file +} diff --git a/src/Endpoints/WmsEndpoint.php b/src/Endpoints/WmsEndpoint.php new file mode 100644 index 0000000..9825619 --- /dev/null +++ b/src/Endpoints/WmsEndpoint.php @@ -0,0 +1,81 @@ +doRequest('GetVoorraad'); + + return InventoryResponse::fromResponse($this->validateAndExtractData('GetVoorraadResult', $result)); + } + + /** + * @throws StatuswebErrorResponse + * @throws StatuswebException + */ + public function getArticleInventory(string $articleNumber): InventoryResponse + { + $result = $this->doRequest('GetVoorraadArtikel', ['Artikel' => $articleNumber]); + + return InventoryResponse::fromResponse($this->validateAndExtractData('GetVoorraadArtikelResult', $result)); + } + + /** + * @throws StatuswebErrorResponse + * @throws StatuswebException + */ + public function createDeliveryRequest(DeliveryRequest $request): DeliveryRequestResponse + { + $result = $this->doRequest('PutUitslagverzoek', ['UitslagverzoekData' => $request->toRequest()]); + + return DeliveryRequestResponse::fromResponse($this->validateAndExtractData('PutUitslagverzoekResult', $result)); + } + + /** + * @throws StatuswebErrorResponse + * @throws StatuswebException + */ + public function deleteDeliveryRequest(int $deliveryId): DeleteDeliveryResponse + { + $result = $this->doRequest('DeleteUitslagID', ['UitslagID' => $deliveryId]); + + return DeleteDeliveryResponse::fromResponse($this->validateAndExtractData('DeleteUitslagIDResult', $result)); + } + + /** + * @throws StatuswebErrorResponse + * @throws StatuswebException + */ + public function getDeliveryRequestStatus(int $deliveryId): DeliveryStatusResponse + { + $result = $this->doRequest('GetStatusUitslagID', ['UitslagID' => $deliveryId]); + + return DeliveryStatusResponse::fromResponse($this->validateAndExtractData('GetStatusUitslagIDResult', $result)); + } + + /** + * @throws StatuswebErrorResponse + * @throws StatuswebException + */ + public function getShipmentsByDeliveryRequest(int $deliveryId): SendShipmentsResponse + { + $result = $this->doRequest('GetZendingenViaUitslagID', ['UitslagID' => $deliveryId]); + + return SendShipmentsResponse::fromResponse($this->validateAndExtractData('GetZendingenViaUitslagIDResult', $result)); + } +} diff --git a/src/Enums/CountryCode.php b/src/Enums/CountryCode.php index 40f1c16..76bf836 100644 --- a/src/Enums/CountryCode.php +++ b/src/Enums/CountryCode.php @@ -12,6 +12,7 @@ class CountryCode public const HUNGARY = 36; public const ITALY = 39; public const PORTUGAL = 351; + public const LUXEMBOURG = 352; public const IRELAND = 353; public const FINLAND = 358; public const SLOVENIA = 386; diff --git a/src/Enums/ResponseCode.php b/src/Enums/ResponseCode.php index d334d47..0000bac 100644 --- a/src/Enums/ResponseCode.php +++ b/src/Enums/ResponseCode.php @@ -15,7 +15,8 @@ class ResponseCode public const HOUSE_NUMBER_INVALID = -102; public const POSTAL_CODE_INVALID = -103; public const PLACE_INVALID = -104; - public const COUNTRY_CODE_INVALID = -105; + public const COUNTRY_CODE_DELIVERY_INVALID = -105; + public const COUNTRY_CODE_LOADING_INVALID = -111; public const SHIPMENT_TYPE_INVALID = -107; public const SHIPMENT_ROW_AMOUNT_INVALID = -108; public const SHIPMENT_ROW_UNIT_INVALID = -109; @@ -27,7 +28,7 @@ class ResponseCode public const INSUFFICIENT_STOCK_FOR_SOME_ARTICLES = -300; public const UNKNOWN_ARTICLE = -310; public const NO_AMOUNT_FOR_SOME_ARTICLES = -320; - public const NO_ETA_FOR_SHIPMENT = -320; + public const NO_ETA_FOR_SHIPMENT = -400; public const NO_STATUS_URL_FOR_SHIPMENT = -500; - public const UNKNOWN_RESULT_ID = -550; + public const DELIVERY_REQUEST_NOT_FOUND = -550; } \ No newline at end of file diff --git a/src/Resources/AddShipmentRowResponse.php b/src/Resources/AddShipmentRowResponse.php new file mode 100644 index 0000000..6639c8f --- /dev/null +++ b/src/Resources/AddShipmentRowResponse.php @@ -0,0 +1,133 @@ +shipmentNumber = $shipmentNumber; + return $this; + } + + public function getShipmentNumber(): int + { + return $this->shipmentNumber; + } + + public function setReference(?string $reference): static + { + $this->reference = $reference; + return $this; + } + + public function getReference(): ?string + { + return $this->reference; + } + + public function setLabels(?string $labels): static + { + $this->labels = $labels; + return $this; + } + + public function getLabels(): ?string + { + return $this->labels; + } + + public function setLabelLength(?int $labelLength): static + { + $this->labelLength = $labelLength; + return $this; + } + + public function getLabelLength(): ?int + { + return $this->labelLength; + } + + public function setStatuswebLink(?string $statuswebLink): static + { + $this->statuswebLink = $statuswebLink; + return $this; + } + + public function getStatuswebLink(): ?string + { + return $this->statuswebLink; + } + + /** + * @param string[] $barcodes + */ + public function setBarcodes(array $barcodes): static + { + $this->barcodes = $barcodes; + return $this; + } + + /** @return string[] */ + public function getBarcodes(): array + { + return $this->barcodes; + } + + /** + * @param int[] $rowIds + */ + public function setRowIds(array $rowIds): static + { + $this->rowIds = $rowIds; + return $this; + } + + /** @return int[] */ + public function getRowIds(): array + { + return $this->rowIds; + } + + public static function fromResponse(array $response): static + { + return (new static) + ->setShipmentNumber((int) ($response['Zendingnummer'] ?? 0)) + ->setReference($response['Kenmerk'] ?? null) + ->setLabels($response['Labels'] ?? null) + ->setLabelLength(isset($response['LabelLengte']) ? (int) $response['LabelLengte'] : null) + ->setStatuswebLink($response['StatuswebLink'] ?? null) + ->setBarcodes(self::extractBarcodes($response)) + ->setRowIds(self::extractIds($response['Regel_IDs'] ?? null)); + } + + private static function extractBarcodes(array $response): array + { + if (!isset($response['Barcodes']['BarcodeData'])) { + return []; + } + $data = $response['Barcodes']['BarcodeData']; + if (isset($data['Barcode'])) { + return [$data['Barcode']]; + } + return array_column($data, 'Barcode'); + } + + private static function extractIds(mixed $ids): array + { + if ($ids === null || !is_array($ids)) { + return []; + } + return array_values(array_filter($ids, 'is_numeric')); + } +} diff --git a/src/Resources/Address.php b/src/Resources/Address.php index 267cec5..f7495a5 100644 --- a/src/Resources/Address.php +++ b/src/Resources/Address.php @@ -222,7 +222,7 @@ public function toRequest(): array 'Naam' => $this->getName(), 'Tav' => $this->getToTheAttentionOf(), 'Adres' => $this->getStreet(), - 'Huisnr' => $this->getHouseNumber(), + 'Huisnummer' => $this->getHouseNumber(), 'Postcode' => $this->getPostalCode(), 'Plaats' => $this->getCity(), 'Landcode' => $this->getCountryCode(), diff --git a/src/Resources/AdrData.php b/src/Resources/AdrData.php new file mode 100644 index 0000000..f1e869b --- /dev/null +++ b/src/Resources/AdrData.php @@ -0,0 +1,210 @@ +unNumber = $unNumber; + return $this; + } + + public function getUnNumber(): string + { + return $this->unNumber; + } + + public function setCategory(int $category): static + { + $this->category = $category; + return $this; + } + + public function getCategory(): int + { + return $this->category; + } + + public function setSubstanceName(string $substanceName): static + { + $this->substanceName = $substanceName; + return $this; + } + + public function getSubstanceName(): string + { + return $this->substanceName; + } + + public function setTechnicalName(?string $technicalName): static + { + $this->technicalName = $technicalName; + return $this; + } + + public function getTechnicalName(): ?string + { + return $this->technicalName; + } + + public function setClass(string $class): static + { + $this->class = $class; + return $this; + } + + public function getClass(): string + { + return $this->class; + } + + public function setPackagingGroup(string $packagingGroup): static + { + $this->packagingGroup = $packagingGroup; + return $this; + } + + public function getPackagingGroup(): string + { + return $this->packagingGroup; + } + + public function setLabel(string $label): static + { + $this->label = $label; + return $this; + } + + public function getLabel(): string + { + return $this->label; + } + + public function setFactor(int $factor): static + { + $this->factor = $factor; + return $this; + } + + public function getFactor(): int + { + return $this->factor; + } + + public function setTunnelCode(string $tunnelCode): static + { + $this->tunnelCode = $tunnelCode; + return $this; + } + + public function getTunnelCode(): string + { + return $this->tunnelCode; + } + + public function setIsEnvironmentallyHazardous(bool $isEnvironmentallyHazardous): static + { + $this->isEnvironmentallyHazardous = $isEnvironmentallyHazardous; + return $this; + } + + public function isEnvironmentallyHazardous(): bool + { + return $this->isEnvironmentallyHazardous; + } + + public function setIsWaste(bool $isWaste): static + { + $this->isWaste = $isWaste; + return $this; + } + + public function isWaste(): bool + { + return $this->isWaste; + } + + public function setIsLq(bool $isLq): static + { + $this->isLq = $isLq; + return $this; + } + + public function isLq(): bool + { + return $this->isLq; + } + + public function setWeight(int $weight): static + { + $this->weight = $weight; + return $this; + } + + public function getWeight(): int + { + return $this->weight; + } + + public function setAmount(?int $amount): static + { + $this->amount = $amount; + return $this; + } + + public function getAmount(): ?int + { + return $this->amount; + } + + public function setPackaging(?string $packaging): static + { + $this->packaging = $packaging; + return $this; + } + + public function getPackaging(): ?string + { + return $this->packaging; + } + + public function toRequest(): array + { + return [ + 'Unnummer' => $this->unNumber, + 'Categorie' => $this->category, + 'Stofnaam' => $this->substanceName, + 'TechnischeBenaming' => $this->technicalName, + 'Klasse' => $this->class, + 'VerpakkingsGroep' => $this->packagingGroup, + 'Etiket' => $this->label, + 'Factor' => $this->factor, + 'Tunnelcode' => $this->tunnelCode, + 'IsMilieuGevaarlijk' => $this->isEnvironmentallyHazardous ? 1 : 0, + 'IsAfvalstof' => $this->isWaste ? 1 : 0, + 'IsLQ' => $this->isLq ? 1 : 0, + 'Gewicht' => $this->weight, + 'Aantal' => $this->amount, + 'Verpakking' => $this->packaging, + ]; + } +} diff --git a/src/Resources/BarcodeData.php b/src/Resources/BarcodeData.php new file mode 100644 index 0000000..d81a8ea --- /dev/null +++ b/src/Resources/BarcodeData.php @@ -0,0 +1,22 @@ +barcode; + } + + public function toRequest(): array + { + return ['Barcode' => $this->barcode]; + } +} diff --git a/src/Resources/DeleteShipmentResponse.php b/src/Resources/DeleteShipmentResponse.php index 60f775d..f1b4399 100644 --- a/src/Resources/DeleteShipmentResponse.php +++ b/src/Resources/DeleteShipmentResponse.php @@ -6,60 +6,35 @@ class DeleteShipmentResponse implements Response { - /** - * @var float - */ - private $transportNumber; + private int $shipmentNumber; + private ?string $reference; - /** - * @var string|null - */ - private $reference; - - /** - * @param float $transportNumber - * @return DeleteShipmentResponse - */ - public function setTransportNumber(float $transportNumber): DeleteShipmentResponse + public function setShipmentNumber(int $shipmentNumber): static { - $this->transportNumber = $transportNumber; + $this->shipmentNumber = $shipmentNumber; return $this; } - /** - * @return float - */ - public function getTransportNumber(): float + public function getShipmentNumber(): int { - return $this->transportNumber; + return $this->shipmentNumber; } - /** - * @param string|null $reference - * @return DeleteShipmentResponse - */ - public function setReference(?string $reference): DeleteShipmentResponse + public function setReference(?string $reference): static { $this->reference = $reference; return $this; } - /** - * @return string|null - */ public function getReference(): ?string { return $this->reference; } - /** - * @inheritDoc - * @return DeleteShipmentResponse - */ - public static function fromResponse(array $response): Response + public static function fromResponse(array $response): static { - return (new self) - ->setTransportNumber($response['Vrachtnummer']) + return (new static) + ->setShipmentNumber((int) ($response['Zendingnummer'] ?? 0)) ->setReference($response['Kenmerk'] ?? null); } -} \ No newline at end of file +} diff --git a/src/Resources/DeleteShipmentRowResponse.php b/src/Resources/DeleteShipmentRowResponse.php new file mode 100644 index 0000000..7e797f6 --- /dev/null +++ b/src/Resources/DeleteShipmentRowResponse.php @@ -0,0 +1,40 @@ +shipmentNumber = $shipmentNumber; + return $this; + } + + public function getShipmentNumber(): int + { + return $this->shipmentNumber; + } + + public function setReference(?string $reference): static + { + $this->reference = $reference; + return $this; + } + + public function getReference(): ?string + { + return $this->reference; + } + + public static function fromResponse(array $response): static + { + return (new static) + ->setShipmentNumber((int) ($response['Zendingnummer'] ?? 0)) + ->setReference($response['Kenmerk'] ?? null); + } +} diff --git a/src/Resources/EtaResponse.php b/src/Resources/EtaResponse.php index f489cc1..ab5d189 100644 --- a/src/Resources/EtaResponse.php +++ b/src/Resources/EtaResponse.php @@ -6,60 +6,61 @@ class EtaResponse implements Response { - /** - * @var string - */ - private $from; + private int $shipmentNumber; + private ?string $reference; + private string $from; + private string $until; - /** - * @var string - */ - private $until; + public function setShipmentNumber(int $shipmentNumber): static + { + $this->shipmentNumber = $shipmentNumber; + return $this; + } + + public function getShipmentNumber(): int + { + return $this->shipmentNumber; + } + + public function setReference(?string $reference): static + { + $this->reference = $reference; + return $this; + } + + public function getReference(): ?string + { + return $this->reference; + } - /** - * @param string $from - * @return EtaResponse - */ - public function setFrom(string $from): EtaResponse + public function setFrom(string $from): static { $this->from = $from; return $this; } - /** - * @return string - */ public function getFrom(): string { return $this->from; } - /** - * @param string $until - * @return EtaResponse - */ - public function setUntil(string $until): EtaResponse + public function setUntil(string $until): static { $this->until = $until; return $this; } - /** - * @return string - */ public function getUntil(): string { return $this->until; } - /** - * @inheritDoc - * @return EtaResponse - */ - public static function fromResponse(array $response): Response + public static function fromResponse(array $response): static { - return (new self) - ->setFrom($response['ETA_Van']) - ->setUntil($response['ETA_Tot']); + return (new static) + ->setShipmentNumber((int) ($response['Zendingnummer'] ?? 0)) + ->setReference($response['Kenmerk'] ?? null) + ->setFrom($response['ETA_Van'] ?? '') + ->setUntil($response['ETA_Tot'] ?? ''); } -} \ No newline at end of file +} diff --git a/src/Resources/LabelResponse.php b/src/Resources/LabelResponse.php index 333463d..a93722a 100644 --- a/src/Resources/LabelResponse.php +++ b/src/Resources/LabelResponse.php @@ -6,84 +6,90 @@ class LabelResponse implements Response { - /** - * @var float - */ - private $transportNumber; - - /** - * @var string|null - */ - private $reference; + private int $shipmentNumber; + private ?string $reference; + private ?string $labels; + private ?int $labelLength; + private array $barcodes; - /** - * @var string|null - */ - private $labels; - - /** - * @param float $transportNumber - * @return LabelResponse - */ - public function setTransportNumber(float $transportNumber): LabelResponse + public function setShipmentNumber(int $shipmentNumber): static { - $this->transportNumber = $transportNumber; + $this->shipmentNumber = $shipmentNumber; return $this; } - /** - * @return float - */ - public function getTransportNumber(): float + public function getShipmentNumber(): int { - return $this->transportNumber; + return $this->shipmentNumber; } - /** - * @param string|null $reference - * @return LabelResponse - */ - public function setReference(?string $reference): LabelResponse + public function setReference(?string $reference): static { $this->reference = $reference; return $this; } - /** - * @return string|null - */ public function getReference(): ?string { return $this->reference; } - /** - * @param string|null $labels - * @return LabelResponse - */ - public function setLabels(?string $labels): LabelResponse + public function setLabels(?string $labels): static { $this->labels = $labels; return $this; } - /** - * @return string|null - */ public function getLabels(): ?string { return $this->labels; } + public function setLabelLength(?int $labelLength): static + { + $this->labelLength = $labelLength; + return $this; + } + + public function getLabelLength(): ?int + { + return $this->labelLength; + } + /** - * @inheritDoc - * @return LabelResponse + * @param string[] $barcodes */ - public static function fromResponse(array $response): Response + public function setBarcodes(array $barcodes): static + { + $this->barcodes = $barcodes; + return $this; + } + + /** @return string[] */ + public function getBarcodes(): array { - return (new self) - ->setTransportNumber($response['Vrachtnummer']) + return $this->barcodes; + } + + public static function fromResponse(array $response): static + { + return (new static) + ->setShipmentNumber((int) ($response['Zendingnummer'] ?? 0)) ->setReference($response['Kenmerk'] ?? null) - ->setLabels($response['Labels'] ?? null); + ->setLabels($response['Labels'] ?? null) + ->setLabelLength(isset($response['LabelLengte']) ? (int) $response['LabelLengte'] : null) + ->setBarcodes(self::extractBarcodes($response)); + } + + private static function extractBarcodes(array $response): array + { + if (!isset($response['Barcodes']['BarcodeData'])) { + return []; + } + $data = $response['Barcodes']['BarcodeData']; + if (isset($data['Barcode'])) { + return [$data['Barcode']]; + } + return array_column($data, 'Barcode'); } -} \ No newline at end of file +} diff --git a/src/Resources/PhotoData.php b/src/Resources/PhotoData.php new file mode 100644 index 0000000..e0bf50f --- /dev/null +++ b/src/Resources/PhotoData.php @@ -0,0 +1,79 @@ +filename = $filename; + return $this; + } + + public function getFilename(): string + { + return $this->filename; + } + + public function setPhoto(?string $photo): static + { + $this->photo = $photo; + return $this; + } + + public function getPhoto(): ?string + { + return $this->photo; + } + + public function setPhotoLength(?int $photoLength): static + { + $this->photoLength = $photoLength; + return $this; + } + + public function getPhotoLength(): ?int + { + return $this->photoLength; + } + + public function setLocX(?string $locX): static + { + $this->locX = $locX; + return $this; + } + + public function getLocX(): ?string + { + return $this->locX; + } + + public function setLocY(?string $locY): static + { + $this->locY = $locY; + return $this; + } + + public function getLocY(): ?string + { + return $this->locY; + } + + public static function fromResponse(array $response): static + { + return (new static) + ->setFilename($response['Bestandsnaam'] ?? '') + ->setPhoto($response['Foto'] ?? null) + ->setPhotoLength(isset($response['FotoLengte']) ? (int) $response['FotoLengte'] : null) + ->setLocX($response['LocX'] ?? null) + ->setLocY($response['LocY'] ?? null); + } +} diff --git a/src/Resources/PhotoResponse.php b/src/Resources/PhotoResponse.php new file mode 100644 index 0000000..edd05d6 --- /dev/null +++ b/src/Resources/PhotoResponse.php @@ -0,0 +1,67 @@ +shipmentNumber = $shipmentNumber; + return $this; + } + + public function getShipmentNumber(): int + { + return $this->shipmentNumber; + } + + public function setReference(?string $reference): static + { + $this->reference = $reference; + return $this; + } + + public function getReference(): ?string + { + return $this->reference; + } + + /** + * @param PhotoData[] $photos + */ + public function setPhotos(array $photos): static + { + $this->photos = $photos; + return $this; + } + + /** @return PhotoData[] */ + public function getPhotos(): array + { + return $this->photos; + } + + public static function fromResponse(array $response): static + { + $photos = []; + if (isset($response['Fotos']['FotoData'])) { + $data = $response['Fotos']['FotoData']; + if (isset($data['Bestandsnaam'])) { + $data = [$data]; + } + $photos = array_map(static fn(array $f) => PhotoData::fromResponse($f), $data); + } + + return (new static) + ->setShipmentNumber((int) ($response['Zendingnummer'] ?? 0)) + ->setReference($response['Kenmerk'] ?? null) + ->setPhotos($photos); + } +} diff --git a/src/Resources/PodResponse.php b/src/Resources/PodResponse.php new file mode 100644 index 0000000..48b2f88 --- /dev/null +++ b/src/Resources/PodResponse.php @@ -0,0 +1,92 @@ +shipmentNumber = $shipmentNumber; + return $this; + } + + public function getShipmentNumber(): int + { + return $this->shipmentNumber; + } + + public function setReference(?string $reference): static + { + $this->reference = $reference; + return $this; + } + + public function getReference(): ?string + { + return $this->reference; + } + + public function setPod(?string $pod): static + { + $this->pod = $pod; + return $this; + } + + public function getPod(): ?string + { + return $this->pod; + } + + public function setPodLength(?int $podLength): static + { + $this->podLength = $podLength; + return $this; + } + + public function getPodLength(): ?int + { + return $this->podLength; + } + + public function setLocX(?string $locX): static + { + $this->locX = $locX; + return $this; + } + + public function getLocX(): ?string + { + return $this->locX; + } + + public function setLocY(?string $locY): static + { + $this->locY = $locY; + return $this; + } + + public function getLocY(): ?string + { + return $this->locY; + } + + public static function fromResponse(array $response): static + { + return (new static) + ->setShipmentNumber((int) ($response['Zendingnummer'] ?? 0)) + ->setReference($response['Kenmerk'] ?? null) + ->setPod($response['POD'] ?? null) + ->setPodLength(isset($response['PODLengte']) ? (int) $response['PODLengte'] : null) + ->setLocX($response['LocX'] ?? null) + ->setLocY($response['LocY'] ?? null); + } +} diff --git a/src/Resources/SendShipmentResponse.php b/src/Resources/SendShipmentResponse.php index 02ffc73..63d4dcc 100644 --- a/src/Resources/SendShipmentResponse.php +++ b/src/Resources/SendShipmentResponse.php @@ -6,60 +6,48 @@ class SendShipmentResponse implements Response { - /** - * @var float - */ - private $transportNumber; + private int $shipmentNumber; + private ?string $reference; + private ?string $statuswebLink; - /** - * @var string|null - */ - private $reference; - - /** - * @param float $transportNumber - * @return SendShipmentResponse - */ - public function setTransportNumber(float $transportNumber): SendShipmentResponse + public function setShipmentNumber(int $shipmentNumber): static { - $this->transportNumber = $transportNumber; + $this->shipmentNumber = $shipmentNumber; return $this; } - /** - * @return float - */ - public function getTransportNumber(): float + public function getShipmentNumber(): int { - return $this->transportNumber; + return $this->shipmentNumber; } - /** - * @param string|null $reference - * @return SendShipmentResponse - */ - public function setReference(?string $reference): SendShipmentResponse + public function setReference(?string $reference): static { $this->reference = $reference; return $this; } - /** - * @return string|null - */ public function getReference(): ?string { return $this->reference; } - /** - * @inheritDoc - * @return SendShipmentResponse - */ - public static function fromResponse(array $response): Response + public function setStatuswebLink(?string $statuswebLink): static + { + $this->statuswebLink = $statuswebLink; + return $this; + } + + public function getStatuswebLink(): ?string + { + return $this->statuswebLink; + } + + public static function fromResponse(array $response): static { - return (new self) - ->setTransportNumber($response['Vrachtnummer']) - ->setReference($response['Kenmerk'] ?? null); + return (new static) + ->setShipmentNumber((int) ($response['Zendingnummer'] ?? 0)) + ->setReference($response['Kenmerk'] ?? null) + ->setStatuswebLink($response['StatuswebLink'] ?? null); } -} \ No newline at end of file +} diff --git a/src/Resources/SendShipmentsResponse.php b/src/Resources/SendShipmentsResponse.php index 2d36408..120a61b 100644 --- a/src/Resources/SendShipmentsResponse.php +++ b/src/Resources/SendShipmentsResponse.php @@ -6,38 +6,41 @@ class SendShipmentsResponse implements Response { - /** - * @var SendShipmentResponse[] - */ - private $sendShipmentData; + /** @var SendShipmentResponse[] */ + private array $shipments; /** - * @param SendShipmentResponse[] $sendShipmentData - * @return SendShipmentsResponse + * @param SendShipmentResponse[] $shipments */ - public function setSendShipmentData(array $sendShipmentData): SendShipmentsResponse + public function setShipments(array $shipments): static { - $this->sendShipmentData = $sendShipmentData; + $this->shipments = $shipments; return $this; } - /** - * @return SendShipmentResponse[] - */ - public function getSendShipmentData(): array + /** @return SendShipmentResponse[] */ + public function getShipments(): array { - return $this->sendShipmentData; + return $this->shipments; } - /** - * @inheritDoc - * @return SendShipmentsResponse - */ - public static function fromResponse(array $response): Response + public static function fromResponse(array $response): static { - return (new self) - ->setSendShipmentData(array_map(static function (array $sendShipmentData): SendShipmentResponse { - return SendShipmentResponse::fromResponse($sendShipmentData); - }, $response['Zendingen'] ?? [])); + $zendingen = $response['Zendingen'] ?? []; + + $items = []; + if (isset($zendingen['SendZendingData'])) { + $data = $zendingen['SendZendingData']; + // normalize single item (associative) vs multiple items (indexed) + if (isset($data['Zendingnummer'])) { + $data = [$data]; + } + $items = array_map( + static fn(array $item) => SendShipmentResponse::fromResponse($item), + $data, + ); + } + + return (new static)->setShipments($items); } -} \ No newline at end of file +} diff --git a/src/Resources/ShipmentInfoResponse.php b/src/Resources/ShipmentInfoResponse.php new file mode 100644 index 0000000..955096e --- /dev/null +++ b/src/Resources/ShipmentInfoResponse.php @@ -0,0 +1,247 @@ +shipmentNumber = $shipmentNumber; + return $this; + } + + public function getShipmentNumber(): int + { + return $this->shipmentNumber; + } + + public function setReference(?string $reference): static + { + $this->reference = $reference; + return $this; + } + + public function getReference(): ?string + { + return $this->reference; + } + + public function setShipmentType(int $shipmentType): static + { + $this->shipmentType = $shipmentType; + return $this; + } + + public function getShipmentType(): int + { + return $this->shipmentType; + } + + public function setLoadingAddress(?Address $loadingAddress): static + { + $this->loadingAddress = $loadingAddress; + return $this; + } + + public function getLoadingAddress(): ?Address + { + return $this->loadingAddress; + } + + public function setLoadingDate(?string $loadingDate): static + { + $this->loadingDate = $loadingDate; + return $this; + } + + public function getLoadingDate(): ?string + { + return $this->loadingDate; + } + + public function setLoadingTimeFrom(?string $loadingTimeFrom): static + { + $this->loadingTimeFrom = $loadingTimeFrom; + return $this; + } + + public function getLoadingTimeFrom(): ?string + { + return $this->loadingTimeFrom; + } + + public function setLoadingTimeUntil(?string $loadingTimeUntil): static + { + $this->loadingTimeUntil = $loadingTimeUntil; + return $this; + } + + public function getLoadingTimeUntil(): ?string + { + return $this->loadingTimeUntil; + } + + public function setLoadingNote(?string $loadingNote): static + { + $this->loadingNote = $loadingNote; + return $this; + } + + public function getLoadingNote(): ?string + { + return $this->loadingNote; + } + + public function setDeliveryAddress(?Address $deliveryAddress): static + { + $this->deliveryAddress = $deliveryAddress; + return $this; + } + + public function getDeliveryAddress(): ?Address + { + return $this->deliveryAddress; + } + + public function setDeliveryDate(?string $deliveryDate): static + { + $this->deliveryDate = $deliveryDate; + return $this; + } + + public function getDeliveryDate(): ?string + { + return $this->deliveryDate; + } + + public function setDeliveryTimeFrom(?string $deliveryTimeFrom): static + { + $this->deliveryTimeFrom = $deliveryTimeFrom; + return $this; + } + + public function getDeliveryTimeFrom(): ?string + { + return $this->deliveryTimeFrom; + } + + public function setDeliveryTimeUntil(?string $deliveryTimeUntil): static + { + $this->deliveryTimeUntil = $deliveryTimeUntil; + return $this; + } + + public function getDeliveryTimeUntil(): ?string + { + return $this->deliveryTimeUntil; + } + + public function setDeliveryNote(?string $deliveryNote): static + { + $this->deliveryNote = $deliveryNote; + return $this; + } + + public function getDeliveryNote(): ?string + { + return $this->deliveryNote; + } + + /** + * @param array> $shipmentRows + */ + public function setShipmentRows(array $shipmentRows): static + { + $this->shipmentRows = $shipmentRows; + return $this; + } + + /** @return array> */ + public function getShipmentRows(): array + { + return $this->shipmentRows; + } + + public function setCashOnDeliveryAmount(?int $cashOnDeliveryAmount): static + { + $this->cashOnDeliveryAmount = $cashOnDeliveryAmount; + return $this; + } + + public function getCashOnDeliveryAmount(): ?int + { + return $this->cashOnDeliveryAmount; + } + + public static function fromResponse(array $response): static + { + $instance = (new static) + ->setShipmentNumber((int) ($response['Zendingnummer'] ?? 0)) + ->setReference($response['Kenmerk'] ?? null) + ->setShipmentType((int) ($response['Zendingsoort'] ?? 0)) + ->setLoadingDate($response['Laaddatum'] ?? null) + ->setLoadingTimeFrom($response['Laadvanaf'] ?? null) + ->setLoadingTimeUntil($response['Laadtotmet'] ?? null) + ->setLoadingNote($response['Laadopmerking'] ?? null) + ->setDeliveryDate($response['Losdatum'] ?? null) + ->setDeliveryTimeFrom($response['Losvanaf'] ?? null) + ->setDeliveryTimeUntil($response['Lostotmet'] ?? null) + ->setDeliveryNote($response['Losopmerking'] ?? null) + ->setCashOnDeliveryAmount(isset($response['Rembours']) ? (int) $response['Rembours'] : null) + ->setShipmentRows(self::extractRows($response)); + + if (isset($response['Laadadres'])) { + $instance->setLoadingAddress(self::parseAddress($response['Laadadres'])); + } + + if (isset($response['LosAdres'])) { + $instance->setDeliveryAddress(self::parseAddress($response['LosAdres'])); + } + + return $instance; + } + + private static function parseAddress(array $data): Address + { + return (new Address) + ->setName($data['Naam'] ?? '') + ->setToTheAttentionOf($data['Tav'] ?? null) + ->setStreet($data['Adres'] ?? '') + ->setHouseNumber($data['Huisnummer'] ?? '') + ->setPostalCode($data['Postcode'] ?? '') + ->setCity($data['Plaats'] ?? '') + ->setCountryCode((int) ($data['Landcode'] ?? 0)) + ->setPhoneNumber($data['Telnr'] ?? null) + ->setEmail($data['Email'] ?? null); + } + + private static function extractRows(array $response): array + { + if (!isset($response['Zendingregels']['ZendingregelData'])) { + return []; + } + $data = $response['Zendingregels']['ZendingregelData']; + if (isset($data['Aantal'])) { + $data = [$data]; + } + return $data; + } +} diff --git a/src/Resources/ShipmentResponse.php b/src/Resources/ShipmentResponse.php index 74b7eda..c586ace 100644 --- a/src/Resources/ShipmentResponse.php +++ b/src/Resources/ShipmentResponse.php @@ -6,84 +6,128 @@ class ShipmentResponse implements Response { - /** - * @var float - */ - private $transportNumber; - - /** - * @var string|null - */ - private $reference; - - /** - * @var string|null - */ - private $labels; + private int $shipmentNumber; + private ?string $reference; + private ?string $labels; + private ?int $labelLength; + private ?string $statuswebLink; + private array $barcodes; + private array $rowIds; - /** - * @param float $transportNumber - * @return ShipmentResponse - */ - public function setTransportNumber(float $transportNumber): ShipmentResponse + public function setShipmentNumber(int $shipmentNumber): static { - $this->transportNumber = $transportNumber; + $this->shipmentNumber = $shipmentNumber; return $this; } - /** - * @return float - */ - public function getTransportNumber(): float + public function getShipmentNumber(): int { - return $this->transportNumber; + return $this->shipmentNumber; } - /** - * @param string|null $reference - * @return ShipmentResponse - */ - public function setReference(?string $reference): ShipmentResponse + public function setReference(?string $reference): static { $this->reference = $reference; return $this; } - /** - * @return string|null - */ public function getReference(): ?string { return $this->reference; } - /** - * @param string|null $labels - * @return ShipmentResponse - */ - public function setLabels(?string $labels): ShipmentResponse + public function setLabels(?string $labels): static { $this->labels = $labels; return $this; } - /** - * @return string|null - */ public function getLabels(): ?string { return $this->labels; } + public function setLabelLength(?int $labelLength): static + { + $this->labelLength = $labelLength; + return $this; + } + + public function getLabelLength(): ?int + { + return $this->labelLength; + } + + public function setStatuswebLink(?string $statuswebLink): static + { + $this->statuswebLink = $statuswebLink; + return $this; + } + + public function getStatuswebLink(): ?string + { + return $this->statuswebLink; + } + + /** + * @param string[] $barcodes + */ + public function setBarcodes(array $barcodes): static + { + $this->barcodes = $barcodes; + return $this; + } + + /** @return string[] */ + public function getBarcodes(): array + { + return $this->barcodes; + } + /** - * @inheritDoc - * @return ShipmentResponse + * @param int[] $rowIds */ - public static function fromResponse(array $response): Response + public function setRowIds(array $rowIds): static + { + $this->rowIds = $rowIds; + return $this; + } + + /** @return int[] */ + public function getRowIds(): array + { + return $this->rowIds; + } + + public static function fromResponse(array $response): static { - return (new self) - ->setTransportNumber($response['Vrachtnummer']) + return (new static) + ->setShipmentNumber((int) ($response['Zendingnummer'] ?? 0)) ->setReference($response['Kenmerk'] ?? null) - ->setLabels($response['Labels'] ?? null); + ->setLabels($response['Labels'] ?? null) + ->setLabelLength(isset($response['LabelLengte']) ? (int) $response['LabelLengte'] : null) + ->setStatuswebLink($response['StatuswebLink'] ?? null) + ->setBarcodes(self::extractBarcodes($response)) + ->setRowIds(self::extractIds($response['Regel_IDs'] ?? null)); + } + + private static function extractBarcodes(array $response): array + { + if (!isset($response['Barcodes']['BarcodeData'])) { + return []; + } + $data = $response['Barcodes']['BarcodeData']; + if (isset($data['Barcode'])) { + return [$data['Barcode']]; + } + return array_column($data, 'Barcode'); + } + + private static function extractIds(mixed $ids): array + { + if ($ids === null || !is_array($ids)) { + return []; + } + return array_values(array_filter($ids, 'is_numeric')); } -} \ No newline at end of file +} diff --git a/src/Resources/ShipmentRow.php b/src/Resources/ShipmentRow.php index 0e5fa9c..fb35cae 100644 --- a/src/Resources/ShipmentRow.php +++ b/src/Resources/ShipmentRow.php @@ -6,242 +6,165 @@ class ShipmentRow implements Request { - /** - * @var int - */ - private $amount; - - /** - * @var string - */ - private $unit; - - /** - * @var int - */ - private $weight; - - /** - * @var string|null - */ - private $description; - - /** - * @var string|null - */ - private $articleNumber; - - /** - * @var int|null - */ - private $length; - - /** - * @var int|null - */ - private $width; - - /** - * @var int|null - */ - private $height; - - /** - * @var int|null - */ - private $volume; - - /** - * @var int|null - */ - private $loadMeters; - - /** - * @param int $amount - * @return ShipmentRow - */ - public function setAmount(int $amount): ShipmentRow + private int $amount; + private string $unit; + private int $weight; + private ?string $description = null; + private ?string $articleNumber = null; + private ?int $length = null; + private ?int $width = null; + private ?int $height = null; + private ?int $volume = null; + private ?int $loadMeters = null; + /** @var BarcodeData[] */ + private array $barcodes = []; + private ?AdrData $adr = null; + + public function setAmount(int $amount): static { $this->amount = $amount; return $this; } - /** - * @return int - */ public function getAmount(): int { return $this->amount; } - /** - * @param string $unit - * @return ShipmentRow - */ - public function setUnit(string $unit): ShipmentRow + public function setUnit(string $unit): static { $this->unit = $unit; return $this; } - /** - * @return string - */ public function getUnit(): string { return $this->unit; } - /** - * @param int $weight - * @return ShipmentRow - */ - public function setWeight(int $weight): ShipmentRow + public function setWeight(int $weight): static { $this->weight = $weight; return $this; } - /** - * @return int - */ public function getWeight(): int { return $this->weight; } - /** - * @param string|null $description - * @return ShipmentRow - */ - public function setDescription(?string $description): ShipmentRow + public function setDescription(?string $description): static { $this->description = $description; return $this; } - /** - * @return string|null - */ public function getDescription(): ?string { return $this->description; } - /** - * @param string|null $articleNumber - * @return ShipmentRow - */ - public function setArticleNumber(?string $articleNumber): ShipmentRow + public function setArticleNumber(?string $articleNumber): static { $this->articleNumber = $articleNumber; return $this; } - /** - * @return string|null - */ public function getArticleNumber(): ?string { return $this->articleNumber; } - /** - * @param int|null $length - * @return ShipmentRow - */ - public function setLength(?int $length): ShipmentRow + public function setLength(?int $length): static { $this->length = $length; return $this; } - /** - * @return int|null - */ public function getLength(): ?int { return $this->length; } - /** - * @param int|null $width - * @return ShipmentRow - */ - public function setWidth(?int $width): ShipmentRow + public function setWidth(?int $width): static { $this->width = $width; return $this; } - /** - * @return int|null - */ public function getWidth(): ?int { return $this->width; } - /** - * @param int|null $height - * @return ShipmentRow - */ - public function setHeight(?int $height): ShipmentRow + public function setHeight(?int $height): static { $this->height = $height; return $this; } - /** - * @return int|null - */ public function getHeight(): ?int { return $this->height; } - /** - * @param int|null $volume - * @return ShipmentRow - */ - public function setVolume(?int $volume): ShipmentRow + public function setVolume(?int $volume): static { $this->volume = $volume; return $this; } - /** - * @return int|null - */ public function getVolume(): ?int { return $this->volume; } - /** - * @param int|null $loadMeters - * @return ShipmentRow - */ - public function setLoadMeters(?int $loadMeters): ShipmentRow + public function setLoadMeters(?int $loadMeters): static { $this->loadMeters = $loadMeters; return $this; } - /** - * @return int|null - */ public function getLoadMeters(): ?int { return $this->loadMeters; } /** - * @inheritDoc + * @param BarcodeData[] $barcodes */ + public function setBarcodes(array $barcodes): static + { + $this->barcodes = $barcodes; + return $this; + } + + /** @return BarcodeData[] */ + public function getBarcodes(): array + { + return $this->barcodes; + } + + public function addBarcode(BarcodeData $barcode): static + { + $this->barcodes[] = $barcode; + return $this; + } + + public function setAdr(?AdrData $adr): static + { + $this->adr = $adr; + return $this; + } + + public function getAdr(): ?AdrData + { + return $this->adr; + } + public function toRequest(): array { - return [ + $data = [ 'Aantal' => $this->getAmount(), 'Eenheid' => $this->getUnit(), 'Gewicht' => $this->getWeight(), @@ -253,5 +176,17 @@ public function toRequest(): array 'Volume' => $this->getVolume(), 'Laadmeters' => $this->getLoadMeters(), ]; + + if ($this->barcodes !== []) { + $data['Barcodes'] = [ + 'BarcodeData' => array_map(static fn(BarcodeData $b) => $b->toRequest(), $this->barcodes), + ]; + } + + if ($this->adr !== null) { + $data['ADR'] = $this->adr->toRequest(); + } + + return $data; } -} \ No newline at end of file +} diff --git a/src/Resources/ShipmentTypeTableItem.php b/src/Resources/ShipmentTypeTableItem.php new file mode 100644 index 0000000..f7fe28a --- /dev/null +++ b/src/Resources/ShipmentTypeTableItem.php @@ -0,0 +1,48 @@ +shipmentType = $shipmentType; + return $this; + } + + public function getShipmentType(): int + { + return $this->shipmentType; + } + + public function setDescription(string $description): static + { + $this->description = $description; + return $this; + } + + public function getDescription(): string + { + return $this->description; + } + + public static function fromResponse(array $response): static + { + return (new static) + ->setShipmentType((int) ($response['Zendingsoort'] ?? 0)) + ->setDescription($response['Omschrijving'] ?? ''); + } + + public static function collectionFromResponse(array $items): array + { + if (isset($items['Zendingsoort'])) { + $items = [$items]; + } + return array_map(static fn(array $item) => static::fromResponse($item), $items); + } +} diff --git a/src/Resources/StatusDataResponse.php b/src/Resources/StatusDataResponse.php index 9b37dee..43353a1 100644 --- a/src/Resources/StatusDataResponse.php +++ b/src/Resources/StatusDataResponse.php @@ -6,204 +6,113 @@ class StatusDataResponse implements Response { - /** - * @var float - */ - private $transportNumber; - - /** - * @var string|null - */ - private $reference; - - /** - * @var string - */ - private $date; - - /** - * @var string - */ - private $time; - - /** - * @var int - */ - private $statusNumber; - - /** - * @var string - */ - private $statusDescription; - - /** - * @var string|null - */ - private $note; - - /** - * @var int - */ - private $uid; - - /** - * @param float $transportNumber - * @return StatusDataResponse - */ - public function setTransportNumber(float $transportNumber): StatusDataResponse - { - $this->transportNumber = $transportNumber; + private int $shipmentNumber; + private ?string $reference; + private string $date; + private string $time; + private int $statusNumber; + private string $statusDescription; + private ?string $note; + private int $uid; + + public function setShipmentNumber(int $shipmentNumber): static + { + $this->shipmentNumber = $shipmentNumber; return $this; } - /** - * @return float - */ - public function getTransportNumber(): float + public function getShipmentNumber(): int { - return $this->transportNumber; + return $this->shipmentNumber; } - /** - * @param string|null $reference - * @return StatusDataResponse - */ - public function setReference(?string $reference): StatusDataResponse + public function setReference(?string $reference): static { $this->reference = $reference; return $this; } - /** - * @return string|null - */ public function getReference(): ?string { return $this->reference; } - /** - * @param string $date - * @return StatusDataResponse - */ - public function setDate(string $date): StatusDataResponse + public function setDate(string $date): static { $this->date = $date; return $this; } - /** - * @return string - */ public function getDate(): string { return $this->date; } - /** - * @param string $time - * @return StatusDataResponse - */ - public function setTime(string $time): StatusDataResponse + public function setTime(string $time): static { $this->time = $time; return $this; } - /** - * @return string - */ public function getTime(): string { return $this->time; } - /** - * @param int $statusNumber - * @return StatusDataResponse - */ - public function setStatusNumber(int $statusNumber): StatusDataResponse + public function setStatusNumber(int $statusNumber): static { $this->statusNumber = $statusNumber; return $this; } - /** - * @return int - */ public function getStatusNumber(): int { return $this->statusNumber; } - /** - * @param string $statusDescription - * @return StatusDataResponse - */ - public function setStatusDescription(string $statusDescription): StatusDataResponse + public function setStatusDescription(string $statusDescription): static { $this->statusDescription = $statusDescription; return $this; } - /** - * @return string - */ public function getStatusDescription(): string { return $this->statusDescription; } - /** - * @param string|null $note - * @return StatusDataResponse - */ - public function setNote(?string $note): StatusDataResponse + public function setNote(?string $note): static { $this->note = $note; return $this; } - /** - * @return string|null - */ public function getNote(): ?string { return $this->note; } - /** - * @param int $uid - * @return StatusDataResponse - */ - public function setUid(int $uid): StatusDataResponse + public function setUid(int $uid): static { $this->uid = $uid; return $this; } - /** - * @return int - */ public function getUid(): int { return $this->uid; } - /** - * @inheritDoc - * @return StatusDataResponse - */ - public static function fromResponse(array $response): Response + public static function fromResponse(array $response): static { - return (new self) - ->setTransportNumber($response['Vrachtnummer']) + return (new static) + ->setShipmentNumber((int) ($response['Zendingnummer'] ?? 0)) ->setReference($response['Kenmerk'] ?? null) - ->setDate($response['Datum']) - ->setTime($response['Tijd']) - ->setStatusNumber($response['StatusNummer']) - ->setStatusDescription($response['StatusOmschrijving']) - ->setNote($response['Opmerking']) - ->setUid($response['UID']); - } -} \ No newline at end of file + ->setDate($response['Datum'] ?? '') + ->setTime($response['Tijd'] ?? '') + ->setStatusNumber((int) ($response['StatusNummer'] ?? 0)) + ->setStatusDescription($response['StatusOmschrijving'] ?? '') + ->setNote($response['Opmerking'] ?? null) + ->setUid((int) ($response['UID'] ?? 0)); + } +} diff --git a/src/Resources/StatusResponse.php b/src/Resources/StatusResponse.php index f7a6410..2d61878 100644 --- a/src/Resources/StatusResponse.php +++ b/src/Resources/StatusResponse.php @@ -6,38 +6,67 @@ class StatusResponse implements Response { - /** - * @var StatusDataResponse[] - */ - private $statuses; + /** @var StatusDataResponse[] */ + private array $statuses; + private ?string $mark; + private bool $hasMore; /** * @param StatusDataResponse[] $statuses - * @return StatusResponse */ - public function setStatuses(array $statuses): StatusResponse + public function setStatuses(array $statuses): static { $this->statuses = $statuses; return $this; } - /** - * @return StatusDataResponse[] - */ + /** @return StatusDataResponse[] */ public function getStatuses(): array { return $this->statuses; } - /** - * @inheritDoc - * @return StatusResponse - */ - public static function fromResponse(array $response): Response + public function setMark(?string $mark): static + { + $this->mark = $mark; + return $this; + } + + public function getMark(): ?string + { + return $this->mark; + } + + public function setHasMore(bool $hasMore): static + { + $this->hasMore = $hasMore; + return $this; + } + + public function hasMore(): bool { - return (new self) - ->setStatuses(array_map(static function (array $statusData) { - return StatusDataResponse::fromResponse($statusData); - }, $response['Status'])); + return $this->hasMore; + } + + public static function fromResponse(array $response): static + { + $statusData = $response['Status'] ?? []; + + $items = []; + if (isset($statusData['StatusMeldingData'])) { + $data = $statusData['StatusMeldingData']; + if (isset($data['Zendingnummer'])) { + $data = [$data]; + } + $items = array_map( + static fn(array $item) => StatusDataResponse::fromResponse($item), + $data, + ); + } + + return (new static) + ->setStatuses($items) + ->setMark($response['Mark'] ?? null) + ->setHasMore(($response['More'] ?? 0) === 1); } -} \ No newline at end of file +} diff --git a/src/Resources/StatusTableItem.php b/src/Resources/StatusTableItem.php new file mode 100644 index 0000000..2474763 --- /dev/null +++ b/src/Resources/StatusTableItem.php @@ -0,0 +1,48 @@ +status = $status; + return $this; + } + + public function getStatus(): int + { + return $this->status; + } + + public function setDescription(string $description): static + { + $this->description = $description; + return $this; + } + + public function getDescription(): string + { + return $this->description; + } + + public static function fromResponse(array $response): static + { + return (new static) + ->setStatus((int) ($response['Status'] ?? 0)) + ->setDescription($response['Omschrijving'] ?? ''); + } + + public static function collectionFromResponse(array $items): array + { + if (isset($items['Status'])) { + $items = [$items]; + } + return array_map(static fn(array $item) => static::fromResponse($item), $items); + } +} diff --git a/src/Resources/StatusweblinkResponse.php b/src/Resources/StatusweblinkResponse.php new file mode 100644 index 0000000..3f05cd5 --- /dev/null +++ b/src/Resources/StatusweblinkResponse.php @@ -0,0 +1,53 @@ +shipmentNumber = $shipmentNumber; + return $this; + } + + public function getShipmentNumber(): int + { + return $this->shipmentNumber; + } + + public function setReference(?string $reference): static + { + $this->reference = $reference; + return $this; + } + + public function getReference(): ?string + { + return $this->reference; + } + + public function setStatuswebLink(string $statuswebLink): static + { + $this->statuswebLink = $statuswebLink; + return $this; + } + + public function getStatuswebLink(): string + { + return $this->statuswebLink; + } + + public static function fromResponse(array $response): static + { + return (new static) + ->setShipmentNumber((int) ($response['Zendingnummer'] ?? 0)) + ->setReference($response['Kenmerk'] ?? null) + ->setStatuswebLink($response['Statusweblink'] ?? ''); + } +} diff --git a/src/Resources/Wms/ArticleData.php b/src/Resources/Wms/ArticleData.php new file mode 100644 index 0000000..9da93d8 --- /dev/null +++ b/src/Resources/Wms/ArticleData.php @@ -0,0 +1,32 @@ +articleNumber; + } + + public function getAmount(): int + { + return $this->amount; + } + + public function toRequest(): array + { + return [ + 'Artikelnr' => $this->articleNumber, + 'Aantal' => $this->amount, + ]; + } +} diff --git a/src/Resources/Wms/DeleteDeliveryResponse.php b/src/Resources/Wms/DeleteDeliveryResponse.php new file mode 100644 index 0000000..230c311 --- /dev/null +++ b/src/Resources/Wms/DeleteDeliveryResponse.php @@ -0,0 +1,13 @@ +deliveryAddress = $deliveryAddress; + return $this; + } + + public function getDeliveryAddress(): Address + { + return $this->deliveryAddress; + } + + public function addArticle(ArticleData $article): static + { + $this->articles[] = $article; + return $this; + } + + /** + * @param ArticleData[] $articles + */ + public function setArticles(array $articles): static + { + $this->articles = $articles; + return $this; + } + + /** @return ArticleData[] */ + public function getArticles(): array + { + return $this->articles; + } + + public function setDeliveryNote(?string $deliveryNote): static + { + $this->deliveryNote = $deliveryNote; + return $this; + } + + public function getDeliveryNote(): ?string + { + return $this->deliveryNote; + } + + public function setDeliveryDate(?string $deliveryDate): static + { + $this->deliveryDate = $deliveryDate; + return $this; + } + + public function getDeliveryDate(): ?string + { + return $this->deliveryDate; + } + + public function setDeliveryTimeFrom(?string $deliveryTimeFrom): static + { + $this->deliveryTimeFrom = $deliveryTimeFrom; + return $this; + } + + public function getDeliveryTimeFrom(): ?string + { + return $this->deliveryTimeFrom; + } + + public function setDeliveryTimeUntil(?string $deliveryTimeUntil): static + { + $this->deliveryTimeUntil = $deliveryTimeUntil; + return $this; + } + + public function getDeliveryTimeUntil(): ?string + { + return $this->deliveryTimeUntil; + } + + public function setDirectSend(bool $directSend): static + { + $this->directSend = $directSend; + return $this; + } + + public function isDirectSend(): bool + { + return $this->directSend; + } + + public function setReference(?string $reference): static + { + $this->reference = $reference; + return $this; + } + + public function getReference(): ?string + { + return $this->reference; + } + + public function setCashOnDeliveryAmount(?int $cashOnDeliveryAmount): static + { + $this->cashOnDeliveryAmount = $cashOnDeliveryAmount; + return $this; + } + + public function getCashOnDeliveryAmount(): ?int + { + return $this->cashOnDeliveryAmount; + } + + public function setShipmentType(int $shipmentType): static + { + $this->shipmentType = $shipmentType; + return $this; + } + + public function getShipmentType(): int + { + return $this->shipmentType; + } + + public function toRequest(): array + { + return [ + 'Losadres' => $this->deliveryAddress->toRequest(), + 'Artikels' => [ + 'ArtikelData' => array_map(static fn(ArticleData $a) => $a->toRequest(), $this->articles), + ], + 'Losopmerking' => $this->deliveryNote, + 'Losdatum' => $this->deliveryDate, + 'Losvanaf' => $this->deliveryTimeFrom, + 'Lostotmet' => $this->deliveryTimeUntil, + 'DirectSend' => $this->directSend ? 1 : 0, + 'Kenmerk' => $this->reference, + 'Rembours' => $this->cashOnDeliveryAmount, + 'Zendingsoort' => $this->shipmentType, + ]; + } +} diff --git a/src/Resources/Wms/DeliveryRequestResponse.php b/src/Resources/Wms/DeliveryRequestResponse.php new file mode 100644 index 0000000..5a316e9 --- /dev/null +++ b/src/Resources/Wms/DeliveryRequestResponse.php @@ -0,0 +1,27 @@ +deliveryId = $deliveryId; + return $this; + } + + public function getDeliveryId(): int + { + return $this->deliveryId; + } + + public static function fromResponse(array $response): static + { + return (new static) + ->setDeliveryId((int) ($response['UitslagID'] ?? 0)); + } +} diff --git a/src/Resources/Wms/DeliveryStatusItem.php b/src/Resources/Wms/DeliveryStatusItem.php new file mode 100644 index 0000000..fb6955f --- /dev/null +++ b/src/Resources/Wms/DeliveryStatusItem.php @@ -0,0 +1,79 @@ +articleNumber = $articleNumber; + return $this; + } + + public function getArticleNumber(): string + { + return $this->articleNumber; + } + + public function setArticleDescription(string $articleDescription): static + { + $this->articleDescription = $articleDescription; + return $this; + } + + public function getArticleDescription(): string + { + return $this->articleDescription; + } + + public function setAmount(int $amount): static + { + $this->amount = $amount; + return $this; + } + + public function getAmount(): int + { + return $this->amount; + } + + public function setStatus(int $status): static + { + $this->status = $status; + return $this; + } + + public function getStatus(): int + { + return $this->status; + } + + public function setStatusDescription(string $statusDescription): static + { + $this->statusDescription = $statusDescription; + return $this; + } + + public function getStatusDescription(): string + { + return $this->statusDescription; + } + + public static function fromResponse(array $response): static + { + return (new static) + ->setArticleNumber($response['Artikelnr'] ?? '') + ->setArticleDescription($response['ArtikelOmschrijving'] ?? '') + ->setAmount((int) ($response['Aantal'] ?? 0)) + ->setStatus((int) ($response['Status'] ?? 0)) + ->setStatusDescription($response['StatusOmschrijving'] ?? ''); + } +} diff --git a/src/Resources/Wms/DeliveryStatusResponse.php b/src/Resources/Wms/DeliveryStatusResponse.php new file mode 100644 index 0000000..e6e35fa --- /dev/null +++ b/src/Resources/Wms/DeliveryStatusResponse.php @@ -0,0 +1,40 @@ +items = $items; + return $this; + } + + /** @return DeliveryStatusItem[] */ + public function getItems(): array + { + return $this->items; + } + + public static function fromResponse(array $response): static + { + $items = []; + if (isset($response['ArtikelStatus']['ArtikelStatusData'])) { + $data = $response['ArtikelStatus']['ArtikelStatusData']; + if (isset($data['Artikelnr'])) { + $data = [$data]; + } + $items = array_map(static fn(array $item) => DeliveryStatusItem::fromResponse($item), $data); + } + + return (new static)->setItems($items); + } +} diff --git a/src/Resources/Wms/InventoryItem.php b/src/Resources/Wms/InventoryItem.php new file mode 100644 index 0000000..d6764c1 --- /dev/null +++ b/src/Resources/Wms/InventoryItem.php @@ -0,0 +1,53 @@ +articleNumber = $articleNumber; + return $this; + } + + public function getArticleNumber(): string + { + return $this->articleNumber; + } + + public function setArticleDescription(string $articleDescription): static + { + $this->articleDescription = $articleDescription; + return $this; + } + + public function getArticleDescription(): string + { + return $this->articleDescription; + } + + public function setAmount(int $amount): static + { + $this->amount = $amount; + return $this; + } + + public function getAmount(): int + { + return $this->amount; + } + + public static function fromResponse(array $response): static + { + return (new static) + ->setArticleNumber($response['Artikelnr'] ?? '') + ->setArticleDescription($response['ArtikelOmschrijving'] ?? '') + ->setAmount((int) ($response['Aantal'] ?? 0)); + } +} diff --git a/src/Resources/Wms/InventoryResponse.php b/src/Resources/Wms/InventoryResponse.php new file mode 100644 index 0000000..80c9ad3 --- /dev/null +++ b/src/Resources/Wms/InventoryResponse.php @@ -0,0 +1,40 @@ +items = $items; + return $this; + } + + /** @return InventoryItem[] */ + public function getItems(): array + { + return $this->items; + } + + public static function fromResponse(array $response): static + { + $items = []; + if (isset($response['Voorraad']['ArtikelVoorraadData'])) { + $data = $response['Voorraad']['ArtikelVoorraadData']; + if (isset($data['Artikelnr'])) { + $data = [$data]; + } + $items = array_map(static fn(array $item) => InventoryItem::fromResponse($item), $data); + } + + return (new static)->setItems($items); + } +} From b10798df175caf09f2e4ce63d24ada08276f859d Mon Sep 17 00:00:00 2001 From: jacobdekeizer Date: Mon, 22 Jun 2026 20:36:04 +0200 Subject: [PATCH 2/7] Revert casing back to original --- src/Endpoints/BaseEndpoint.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Endpoints/BaseEndpoint.php b/src/Endpoints/BaseEndpoint.php index 2148f21..e9ed11a 100644 --- a/src/Endpoints/BaseEndpoint.php +++ b/src/Endpoints/BaseEndpoint.php @@ -40,12 +40,12 @@ protected function validateAndExtractData(string $key, array $result): array protected function validateResponse(array $data): void { - if (array_key_exists('ErrorCode', $data) === false) { + if (array_key_exists('Errorcode', $data) === false) { throw new StatuswebException('Invalid response: ' . json_encode($data)); } - if ($data['ErrorCode'] !== ResponseCode::OK) { - throw StatuswebErrorResponse::fromCode($data['ErrorCode'], $data['ErrorString'] ?? ''); + if ($data['Errorcode'] !== ResponseCode::OK) { + throw StatuswebErrorResponse::fromCode($data['Errorcode'], $data['Errorstring'] ?? ''); } } From 0fa01c0cddbde4de53fcc5b545e78da4133a9048 Mon Sep 17 00:00:00 2001 From: jacobdekeizer Date: Mon, 22 Jun 2026 20:37:55 +0200 Subject: [PATCH 3/7] Update Address.php --- src/Resources/Address.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Resources/Address.php b/src/Resources/Address.php index f7495a5..267cec5 100644 --- a/src/Resources/Address.php +++ b/src/Resources/Address.php @@ -222,7 +222,7 @@ public function toRequest(): array 'Naam' => $this->getName(), 'Tav' => $this->getToTheAttentionOf(), 'Adres' => $this->getStreet(), - 'Huisnummer' => $this->getHouseNumber(), + 'Huisnr' => $this->getHouseNumber(), 'Postcode' => $this->getPostalCode(), 'Plaats' => $this->getCity(), 'Landcode' => $this->getCountryCode(), From 9e18f4e54832a8c02a47447146e331ef965e97cc Mon Sep 17 00:00:00 2001 From: jacobdekeizer Date: Mon, 22 Jun 2026 20:38:15 +0200 Subject: [PATCH 4/7] Update ShipmentInfoResponse.php --- src/Resources/ShipmentInfoResponse.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Resources/ShipmentInfoResponse.php b/src/Resources/ShipmentInfoResponse.php index 955096e..a207845 100644 --- a/src/Resources/ShipmentInfoResponse.php +++ b/src/Resources/ShipmentInfoResponse.php @@ -225,7 +225,7 @@ private static function parseAddress(array $data): Address ->setName($data['Naam'] ?? '') ->setToTheAttentionOf($data['Tav'] ?? null) ->setStreet($data['Adres'] ?? '') - ->setHouseNumber($data['Huisnummer'] ?? '') + ->setHouseNumber($data['Huisnr'] ?? '') ->setPostalCode($data['Postcode'] ?? '') ->setCity($data['Plaats'] ?? '') ->setCountryCode((int) ($data['Landcode'] ?? 0)) From b6964aafa574b72161a210179e7afecb7851235e Mon Sep 17 00:00:00 2001 From: jacobdekeizer Date: Mon, 22 Jun 2026 20:44:05 +0200 Subject: [PATCH 5/7] Remove Barcodes and ADR from ShipmentRow SOAP request WSDL does not define these fields on ZendingregelData; sending them causes SOAP encoding errors. Properties remain on the class. Co-Authored-By: Claude Sonnet 4.6 --- src/Resources/ShipmentRow.php | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/Resources/ShipmentRow.php b/src/Resources/ShipmentRow.php index fb35cae..c58df4a 100644 --- a/src/Resources/ShipmentRow.php +++ b/src/Resources/ShipmentRow.php @@ -177,16 +177,6 @@ public function toRequest(): array 'Laadmeters' => $this->getLoadMeters(), ]; - if ($this->barcodes !== []) { - $data['Barcodes'] = [ - 'BarcodeData' => array_map(static fn(BarcodeData $b) => $b->toRequest(), $this->barcodes), - ]; - } - - if ($this->adr !== null) { - $data['ADR'] = $this->adr->toRequest(); - } - return $data; } } From f852cd125a3fdcafd48920b7c948d759df318acf Mon Sep 17 00:00:00 2001 From: jacobdekeizer Date: Mon, 22 Jun 2026 20:46:22 +0200 Subject: [PATCH 6/7] Update CHANGELOG.md --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b18ce65..ce94719 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,6 @@ - PHP requirement raised to `>=8.5` - Statusweb SOAP API upgraded from v4 to v6 - All `Vrachtnummer` parameters and response fields renamed to `Zendingnummer` (shipment number) -- `Address::toRequest()` field `Huisnr` renamed to `Huisnummer` (matches v6 API) - `ShipmentsEndpoint::getStatus()` parameter changed from `float` to `int` - `ShipmentsEndpoint::delete()` parameter changed from `float` to `int` - `ShipmentsEndpoint::getStatusUrl()` now returns `StatusweblinkResponse` instead of `string` @@ -59,7 +58,7 @@ - `Wms\DeliveryStatusItem`, `Wms\DeliveryStatusResponse` #### Enhancements to existing resources -- `ShipmentRow` — added `Barcodes` and `ADR` fields +- `ShipmentRow` — added `barcodes` (BarcodeData[]) and `adr` (AdrData) properties (not sent in `PutZending`; API does not accept these fields in `ZendingregelData`) - `ShipmentResponse` — added `statuswebLink`, `labelLength`, `barcodes`, `rowIds` - `SendShipmentResponse` — added `statuswebLink` - `LabelResponse` — added `labelLength`, `barcodes` From ae5b5ae53c77c379dc2cb0fa2bd9e51912135d40 Mon Sep 17 00:00:00 2001 From: jacobdekeizer Date: Mon, 22 Jun 2026 21:08:21 +0200 Subject: [PATCH 7/7] Include Barcodes and ADR in ShipmentRow SOAP request PHP 8.5 SOAP encoder validates array keys against the WSDL v6 type definition for ZendingregelData, which includes Barcodes and ADR. Omitting them causes "Encoding: object has no 'Barcodes/ADR' property". Send null when not set. --- src/Resources/ShipmentRow.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Resources/ShipmentRow.php b/src/Resources/ShipmentRow.php index c58df4a..e795488 100644 --- a/src/Resources/ShipmentRow.php +++ b/src/Resources/ShipmentRow.php @@ -164,7 +164,9 @@ public function getAdr(): ?AdrData public function toRequest(): array { - $data = [ + $barcodes = array_map(static fn(BarcodeData $b) => $b->toRequest(), $this->barcodes); + + return [ 'Aantal' => $this->getAmount(), 'Eenheid' => $this->getUnit(), 'Gewicht' => $this->getWeight(), @@ -175,8 +177,8 @@ public function toRequest(): array 'Hoogte' => $this->getHeight(), 'Volume' => $this->getVolume(), 'Laadmeters' => $this->getLoadMeters(), + 'Barcodes' => $barcodes ? ['BarcodeData' => $barcodes] : null, + 'ADR' => $this->adr?->toRequest(), ]; - - return $data; } }