Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions src/MyParcelComApi.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@

namespace MyParcelCom\ApiSdk;

use DateMalformedStringException;
use DateTimeImmutable;
use DateTimeInterface;
use GuzzleHttp\Psr7\Message;
use GuzzleHttp\Psr7\Request;
use Http\Discovery\HttpClientDiscovery;
use JsonException;
use MyParcelCom\ApiSdk\Authentication\AuthenticatorInterface;
use MyParcelCom\ApiSdk\Collection\ArrayCollection;
use MyParcelCom\ApiSdk\Collection\CollectionInterface as ResourceCollectionInterface;
Expand All @@ -18,6 +22,7 @@
use MyParcelCom\ApiSdk\Http\Exceptions\RequestException;
use MyParcelCom\ApiSdk\Resources\Collection;
use MyParcelCom\ApiSdk\Resources\File;
use MyParcelCom\ApiSdk\Resources\Interfaces\AddressInterface;
use MyParcelCom\ApiSdk\Resources\Interfaces\CarrierInterface;
use MyParcelCom\ApiSdk\Resources\Interfaces\CollectionInterface;
use MyParcelCom\ApiSdk\Resources\Interfaces\FileInterface;
Expand Down Expand Up @@ -989,6 +994,48 @@ public function deleteShipmentSurcharge(ShipmentSurchargeInterface $shipmentSurc
return true;
}

/**
* @return list<array{ date_from: DateTimeImmutable, date_to: DateTimeImmutable }>
* @throws RequestException
* @throws JsonException
* @throws DateMalformedStringException
*/
public function getDeliveryDates(
string $serviceCode,
AddressInterface $address,
DatetimeInterface $startDate,
DatetimeInterface $endDate,
array $serviceOptionCodes = [],
$ttl = self::TTL_10MIN,
): array {
$response = $this->doRequest(
self::PATH_DELIVERY_DATES,
'post',
[
'service_code' => $serviceCode,
'service_option_codes' => $serviceOptionCodes,
'address' => [
'country_code' => $address->getCountryCode(),
'postal_code' => $address->getPostalCode(),
'street_number' => $address->getStreetNumber(),
],
'start_date' => $startDate->format('c'), // ISO 8601 date
'end_date' => $endDate->format('c'), // ISO 8601 date
],
ttl: $ttl,
);

$json = json_decode((string) $response->getBody(), true, 512, JSON_THROW_ON_ERROR);

return array_map(
static fn ($deliveryWindow) => [
'date_from' => new DateTimeImmutable($deliveryWindow['date_from']),
'date_to' => new DateTimeImmutable($deliveryWindow['date_to']),
],
$json['data'],
);
}

/**
* Set the URI of the MyParcel.com API.
*/
Expand Down
47 changes: 43 additions & 4 deletions src/MyParcelComApiInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@

namespace MyParcelCom\ApiSdk;

use DateMalformedStringException;
use DateTimeImmutable;
use DateTimeInterface;
use JsonException;
use MyParcelCom\ApiSdk\Authentication\AuthenticatorInterface;
use MyParcelCom\ApiSdk\Collection\CollectionInterface as ResourceCollectionInterface;
use MyParcelCom\ApiSdk\Exceptions\MyParcelComException;
use MyParcelCom\ApiSdk\Http\Exceptions\RequestException;
use MyParcelCom\ApiSdk\Resources\Interfaces\AddressInterface;
use MyParcelCom\ApiSdk\Resources\Interfaces\CarrierInterface;
use MyParcelCom\ApiSdk\Resources\Interfaces\CollectionInterface;
use MyParcelCom\ApiSdk\Resources\Interfaces\FileInterface;
Expand All @@ -17,7 +22,6 @@
use MyParcelCom\ApiSdk\Resources\Interfaces\ServiceRateInterface;
use MyParcelCom\ApiSdk\Resources\Interfaces\ShipmentInterface;
use MyParcelCom\ApiSdk\Resources\Interfaces\ShopInterface;
use MyParcelCom\ApiSdk\Resources\Shipment;
use Psr\Http\Client\ClientInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\SimpleCache\CacheInterface;
Expand All @@ -26,6 +30,7 @@ interface MyParcelComApiInterface
{
const PATH_CARRIERS = '/carriers';
const PATH_COLLECTIONS = '/collections';
const PATH_DELIVERY_DATES = '/shipping/v2/available-delivery-dates';
const PATH_FILES_ID = '/files/{file_id}';
const PATH_MANIFESTS = '/manifests';
const PATH_MANIFESTS_ID_FILES_ID = '/manifests/{manifest_id}/files/{file_id}';
Expand Down Expand Up @@ -111,7 +116,10 @@ public function getServices(
*
* @throws MyParcelComException
*/
public function getServicesForCarrier(CarrierInterface $carrier, int $ttl = self::TTL_10MIN): ResourceCollectionInterface;
public function getServicesForCarrier(
CarrierInterface $carrier,
int $ttl = self::TTL_10MIN,
): ResourceCollectionInterface;

/**
* Retrieves service rates based on the set filters. Available filters are: service, contract and weight. Note that
Expand Down Expand Up @@ -149,7 +157,10 @@ public function resolveDynamicServiceRates(
*
* @throws MyParcelComException
*/
public function getShipments(ShopInterface $shop = null, int $ttl = self::TTL_NO_CACHE): ResourceCollectionInterface;
public function getShipments(
ShopInterface $shop = null,
int $ttl = self::TTL_NO_CACHE,
): ResourceCollectionInterface;

/**
* Get a specific shipment from the API.
Expand Down Expand Up @@ -242,13 +253,41 @@ public function registerCollection(CollectionInterface|string $collectionId): Co
public function deleteCollection(CollectionInterface $collection): bool;

/**
* @param CollectionInterface $collection
* @param CollectionInterface $collection
* @param array<ShipmentInterface|string> $shipments Either an array of strings or an array of ShipmentInterface objects.
* @return CollectionInterface
*/
public function addShipmentsToCollection(CollectionInterface $collection, array $shipments): CollectionInterface;

public function generateManifestForCollection(CollectionInterface $collection): ManifestInterface;

/**
* Get delivery date time windows from a carrier for the provided service.
* Accepts an optional array of `delivery-window` service option codes
*
* @param string $serviceCode
* @param AddressInterface $address
* @param DateTimeInterface $startDate
* @param DateTimeInterface $endDate
* @param array $serviceOptionCodes
* @param int $ttl
* @return list<array{
* date_from: DateTimeImmutable,
* date_to: DateTimeImmutable
* }>
* @throws RequestException
* @throws JsonException
* @throws DateMalformedStringException
*/
public function getDeliveryDates(
string $serviceCode,
AddressInterface $address,
DatetimeInterface $startDate,
DatetimeInterface $endDate,
array $serviceOptionCodes = [],
$ttl = self::TTL_10MIN,
): array;

/**
* Set the URI of the MyParcel.com API.
*/
Expand Down
43 changes: 43 additions & 0 deletions tests/Feature/MyParcelComApi/DeliveryDatesTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

namespace MyParcelCom\ApiSdk\Tests\Feature\MyParcelComApi;

use DateTime;
use DateTimeImmutable;
use MyParcelCom\ApiSdk\Resources\Address;
use MyParcelCom\ApiSdk\Tests\TestCase;

/**
* @group Shipments
*/
class DeliveryDatesTest extends TestCase
{
public function testItRetrievesDeliveryDates(): void
{
$address = new Address();
$address
->setCountryCode('DE')
->setPostalCode('12345')
->setStreetNumber(221);

$deliveryDates = $this->api->getDeliveryDates(
'service-code',
$address,
new DateTime(),
new DateTime(),
[
'service-option-code-1',
'service-option-code-2',
],
);

$this->assertCount(3, $deliveryDates);

foreach ($deliveryDates as $deliveryDate) {
$this->assertInstanceOf(DateTimeImmutable::class, $deliveryDate['date_from']);
$this->assertInstanceOf(DateTimeImmutable::class, $deliveryDate['date_to']);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"data": [
{
"date_from": "2025-05-01T09:30:00+01:00",
"date_to": "2025-05-01T11:30:00+01:00"
},
{
"date_from": "2025-05-01T12:30:00+01:00",
"date_to": "2025-05-01T14:30:00+01:00"
},
{
"date_from": "2025-05-01T15:30:00+01:00",
"date_to": "2025-05-01T17:30:00+01:00"
}
]
}