Aller au contenu

omnibus/offline

Omnibus offline carrier: the shop ships by itself - configured rates, a tracking number typed by hand, its own counters as pickup points.

Étage
Fournisseur · Omnibus
Version
2.x
Suite de conformité
branchée, CI non lue
Vérifié en réel
Son README ne le dit pas
Licence
MIT
composer require omnibus/offline:2.x-dev

No carrier, for omnisense/omnibus: the shop hands its parcels over itself (its own courier, a post office counter) or keeps them for collection. The gateway calls nothing: prices come from the rates option, the tracking number is the one the shop typed, the pickup points are the shop's own counters (click and collect).

Installation

composer require omnibus/offline

Requires PHP 8.2 and omnisense/omnibus (2.x), nothing else: no HTTP client, no framework. In a Symfony application with Omnibus\Bridge\Symfony\OmnibusBundle, the factory is registered as soon as the package is installed. OfflineGatewayFactory is built without an HTTP client.

Credentials

None: there is no service behind the gateway.

Options

No option is required: (new OfflineGatewayFactory())->create() builds a gateway.

Option Type Default Required
tracking_url ?string null no the public tracking page given with each label; {number} is replaced by the tracking number, URL-encoded (rawurlencode)
pickup_points list [] no the shop's counters, returned by every pickup point search (below)
rates list - no the only way this gateway rates (the rates option)

Each entry of pickup_points:

Key Type Default
id string - required; the id to put in Shipment::$pickupPoint
name string - required; the point's name, also its address's name
street list of strings []
postcode string ''
city string ''
country string FR ISO 3166-1 alpha-2
phone ?string null
latitude, longitude float null
opening_hours map [] ISO weekday (1 = Monday) => list of [open, close] slots, "HH:MM", passed on as written

Shipment options read when booking (Shipment::$options):

Option Default
tracking_number the shipment's reference the number from the post office's receipt or the courier's slip

Capabilities

Request Supported
Rating only with rates (configured prices)
Shipping yes (nothing is booked)
Tracking yes, the status is always UNKNOWN
Pickup yes (the configured pickup_points)
GetSlip no
Cancel no
Paperless no

Behaviour

Rate. Without rates the gateway does not support Rating; with it, the core's ConfiguredRatingAction prices each parcel on its weight band.

Ship. Nothing is booked and no document is made: the label has no content and no url (its format keeps the model's default, application/pdf). The tracking number is, in order, the shipment option tracking_number, the shipment's reference, or 12 random uppercase hexadecimal characters. trackingUrl is tracking_url with {number} replaced, or null when tracking_url is not set.

Track. No request: the answer is a Tracking with the number asked for, the status UNKNOWN and no event. The locale is ignored.

Pickup points. The configured pickup_points, in the configured order, cut to the request's limit. The address searched and the parcel are ignored (the shop's counters are offered wherever the customer is), and distance is always null. The opening hours are kept as configured, each slot cast to two strings: nothing checks that the keys are ISO weekdays or the times HH:MM.

Example

<?php

require __DIR__.'/vendor/autoload.php';

use Omnibus\Model\Address;
use Omnibus\Model\Parcel;
use Omnibus\Model\Shipment;
use Omnibus\Offline\OfflineGatewayFactory;

$offline = (new OfflineGatewayFactory())->create([
    'tracking_url' => 'https://www.laposte.fr/outils/suivre-vos-envois?code={number}',
    'rates' => [
        ['service' => 'letter', 'label' => 'Lettre suivie', 'days' => 3, 'countries' => ['FR'],
            'bands' => [500 => 490, 2000 => 790]],
        ['service' => 'shop', 'label' => 'Retrait en boutique', 'to_pickup_point' => true,
            'bands' => [30000 => 0]],
    ],
    'pickup_points' => [
        ['id' => 'shop', 'name' => 'La boutique', 'street' => ['1 rue de Rivoli'], 'postcode' => '75001',
            'city' => 'Paris', 'country' => 'FR', 'opening_hours' => [2 => [['10:00', '19:00']], 6 => [['10:00', '13:00']]]],
    ],
]);

$shipment = new Shipment(
    new Address('Glitch Art', ['12 rue de la Paix'], '75002', 'Paris', 'FR'),
    new Address('Ada Lovelace', ['3 place Bellecour'], '69002', 'Lyon', 'FR'),
    [new Parcel(450)],
    reference: 'CMD-1042',
    options: ['tracking_number' => '6A12345678901'],
);

foreach ($offline->rate($shipment) as $rate) {
    printf("%-6s %-20s %5.2f %s\n", $rate->service, $rate->label, $rate->amount / 100, $rate->currency);
}

$label = $offline->ship($shipment);
echo $label->trackingNumber, ' ', $label->trackingUrl, "\n";
echo $offline->track($label->trackingNumber)->status->value, "\n";

foreach ($offline->pickupPoints($shipment->recipient) as $point) {
    echo $point->id, ' ', $point->name, ', ', $point->address->city, "\n";
}

Output:

shop   Retrait en boutique   0.00 EUR
letter Lettre suivie         4.90 EUR
6A12345678901 https://www.laposte.fr/outils/suivre-vos-envois?code=6A12345678901
unknown
shop La boutique, Paris

In Symfony:

omnibus:
    gateways:
        retrait:
            factory: offline
            options:
                tracking_url: 'https://www.laposte.fr/outils/suivre-vos-envois?code={number}'
                rates:
                    - { service: shop, label: 'Retrait en boutique', to_pickup_point: true, bands: { 30000: 0 } }
                pickup_points:
                    - { id: shop, name: 'La boutique', street: ['1 rue de Rivoli'], postcode: '75001', city: Paris, country: FR,
                        opening_hours: { 2: [['10:00', '19:00']] } }

Errors

The gateway calls no carrier, so it raises no CarrierException. GetSlip, Cancel and Paperless, and Rating without rates, raise RequestNotSupportedException. A pickup_points entry without id or name is not refused: PHP warns of the undefined key and the value is an empty string.

Verified, and not

Tested: Tests/OfflineGatewayTest.php (the typed tracking number and its URL-encoded link, no document, the UNKNOWN status, no GetSlip, the configured counter returned for an address in another city with its opening hours) and Tests/OfflineContractTest.php, the family's conformance suite (the failure checks are skipped: there is no carrier to fail). The example above was run in the core's harness. There is nothing to verify live.

Responsibility

No third-party service is called. The tracking link points wherever tracking_url says; the carrier's or the post office's terms apply to its page.

Proposer une modification docs/index.md