karrio-teleship 2025.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- karrio/mappers/teleship/__init__.py +4 -0
- karrio/mappers/teleship/hooks.py +27 -0
- karrio/mappers/teleship/mapper.py +114 -0
- karrio/mappers/teleship/proxy.py +239 -0
- karrio/mappers/teleship/settings.py +21 -0
- karrio/plugins/teleship/__init__.py +32 -0
- karrio/providers/teleship/__init__.py +41 -0
- karrio/providers/teleship/duties.py +115 -0
- karrio/providers/teleship/error.py +44 -0
- karrio/providers/teleship/hooks/__init__.py +5 -0
- karrio/providers/teleship/hooks/event.py +163 -0
- karrio/providers/teleship/hooks/oauth.py +103 -0
- karrio/providers/teleship/manifest.py +68 -0
- karrio/providers/teleship/pickup/__init__.py +8 -0
- karrio/providers/teleship/pickup/cancel.py +43 -0
- karrio/providers/teleship/pickup/schedule.py +66 -0
- karrio/providers/teleship/rate.py +287 -0
- karrio/providers/teleship/shipment/__init__.py +9 -0
- karrio/providers/teleship/shipment/cancel.py +48 -0
- karrio/providers/teleship/shipment/create.py +322 -0
- karrio/providers/teleship/tracking.py +100 -0
- karrio/providers/teleship/units.py +154 -0
- karrio/providers/teleship/utils.py +57 -0
- karrio/providers/teleship/webhook/__init__.py +8 -0
- karrio/providers/teleship/webhook/deregister.py +47 -0
- karrio/providers/teleship/webhook/register.py +48 -0
- karrio/schemas/teleship/__init__.py +0 -0
- karrio/schemas/teleship/duties_taxes_request.py +82 -0
- karrio/schemas/teleship/duties_taxes_response.py +28 -0
- karrio/schemas/teleship/error_response.py +17 -0
- karrio/schemas/teleship/manifest_request.py +39 -0
- karrio/schemas/teleship/manifest_response.py +31 -0
- karrio/schemas/teleship/pickup_request.py +31 -0
- karrio/schemas/teleship/pickup_response.py +48 -0
- karrio/schemas/teleship/rate_request.py +128 -0
- karrio/schemas/teleship/rate_response.py +66 -0
- karrio/schemas/teleship/shipment_cancel_request.py +8 -0
- karrio/schemas/teleship/shipment_cancel_response.py +17 -0
- karrio/schemas/teleship/shipment_request.py +137 -0
- karrio/schemas/teleship/shipment_response.py +247 -0
- karrio/schemas/teleship/tracking_request.py +8 -0
- karrio/schemas/teleship/tracking_response.py +52 -0
- karrio/schemas/teleship/webhook_request.py +18 -0
- karrio/schemas/teleship/webhook_response.py +20 -0
- karrio_teleship-2025.5.dist-info/METADATA +44 -0
- karrio_teleship-2025.5.dist-info/RECORD +49 -0
- karrio_teleship-2025.5.dist-info/WHEEL +5 -0
- karrio_teleship-2025.5.dist-info/entry_points.txt +2 -0
- karrio_teleship-2025.5.dist-info/top_level.txt +4 -0
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"""Karrio Teleship webhook event processing implementation."""
|
|
2
|
+
|
|
3
|
+
import hmac
|
|
4
|
+
import typing
|
|
5
|
+
import hashlib
|
|
6
|
+
import karrio.lib as lib
|
|
7
|
+
import karrio.core.models as models
|
|
8
|
+
import karrio.providers.teleship.error as error
|
|
9
|
+
import karrio.providers.teleship.utils as provider_utils
|
|
10
|
+
import karrio.providers.teleship.units as provider_units
|
|
11
|
+
import karrio.schemas.teleship.tracking_response as tracking_res
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def on_webhook_event(
|
|
15
|
+
payload: models.RequestPayload,
|
|
16
|
+
settings: provider_utils.Settings,
|
|
17
|
+
) -> typing.Tuple[models.WebhookEventDetails, typing.List[models.Message]]:
|
|
18
|
+
"""
|
|
19
|
+
webhook payloads follow a structure:
|
|
20
|
+
{
|
|
21
|
+
"eventName": "label.generated",
|
|
22
|
+
"objectType": "shipment",
|
|
23
|
+
"objectId": "6f384ad7-f8bf-40ce-8bf0-715248738f10",
|
|
24
|
+
"data": {
|
|
25
|
+
// Event-specific data (see examples below)
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
if not verify_webhook_signature(payload, settings):
|
|
31
|
+
return None, [
|
|
32
|
+
models.Message(
|
|
33
|
+
code="invalid_signature",
|
|
34
|
+
message=f"Invalid webhook signature for {settings.carrier_name} webhook",
|
|
35
|
+
)
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
messages = error.parse_error_response(payload.body, settings)
|
|
39
|
+
body = lib.to_dict(payload.body) if payload.body else {}
|
|
40
|
+
data = body.get("data") or {}
|
|
41
|
+
|
|
42
|
+
# Extract tracking details from webhook event data
|
|
43
|
+
tracking = lib.identity(
|
|
44
|
+
_extract_webhook_tracking(data, settings)
|
|
45
|
+
if body.get("eventName") == "shipment.updated" and data.get("trackingNumber")
|
|
46
|
+
else None
|
|
47
|
+
)
|
|
48
|
+
details = models.WebhookEventDetails(
|
|
49
|
+
carrier_id=settings.carrier_id,
|
|
50
|
+
carrier_name=settings.carrier_name,
|
|
51
|
+
tracking_number=data.get("trackingNumber"),
|
|
52
|
+
shipment_identifier=body.get("objectId"),
|
|
53
|
+
tracking=tracking,
|
|
54
|
+
shipment=None,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
return details, messages
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _extract_webhook_tracking(
|
|
61
|
+
data: typing.Any,
|
|
62
|
+
settings: provider_utils.Settings,
|
|
63
|
+
) -> models.TrackingDetails:
|
|
64
|
+
"""Extract tracking details from webhook event data.
|
|
65
|
+
|
|
66
|
+
Webhook data structure differs from tracking API response - timestamps include
|
|
67
|
+
milliseconds and the data is nested under 'data' in the webhook payload.
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
tracking = lib.to_object(tracking_res.TrackingResponseType, data)
|
|
71
|
+
last_event = next(iter(tracking.events or []), None)
|
|
72
|
+
status = next(
|
|
73
|
+
(
|
|
74
|
+
status.name
|
|
75
|
+
for status in list(provider_units.TrackingStatus)
|
|
76
|
+
if last_event and last_event.code in status.value
|
|
77
|
+
),
|
|
78
|
+
provider_units.TrackingStatus.in_transit.name,
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
# Teleship webhook timestamps include milliseconds: "2025-11-27T05:48:00.000Z"
|
|
82
|
+
timestamp_formats = ["%Y-%m-%dT%H:%M:%S.%fZ", "%Y-%m-%dT%H:%M:%SZ"]
|
|
83
|
+
|
|
84
|
+
return models.TrackingDetails(
|
|
85
|
+
carrier_id=settings.carrier_id,
|
|
86
|
+
carrier_name=settings.carrier_name,
|
|
87
|
+
tracking_number=tracking.trackingNumber,
|
|
88
|
+
events=[
|
|
89
|
+
models.TrackingEvent(
|
|
90
|
+
date=lib.fdate(event.timestamp, try_formats=timestamp_formats),
|
|
91
|
+
time=lib.flocaltime(event.timestamp, try_formats=timestamp_formats),
|
|
92
|
+
description=event.description,
|
|
93
|
+
code=event.code,
|
|
94
|
+
location=event.location,
|
|
95
|
+
)
|
|
96
|
+
for event in (tracking.events or [])
|
|
97
|
+
],
|
|
98
|
+
delivered=status == "delivered",
|
|
99
|
+
status=status,
|
|
100
|
+
estimated_delivery=lib.fdate(
|
|
101
|
+
tracking.estimatedDelivery, try_formats=timestamp_formats
|
|
102
|
+
),
|
|
103
|
+
info=models.TrackingInfo(
|
|
104
|
+
shipment_service=tracking.firstMile.carrier,
|
|
105
|
+
carrier_tracking_link=settings.tracking_url.format(tracking.trackingNumber),
|
|
106
|
+
customer_name=tracking.shipTo.address.city,
|
|
107
|
+
shipment_destination_country=tracking.shipTo.address.country,
|
|
108
|
+
shipment_origin_country=tracking.shipFrom.address.country,
|
|
109
|
+
),
|
|
110
|
+
meta=dict(
|
|
111
|
+
shipment_id=tracking.shipmentId,
|
|
112
|
+
customer_reference=tracking.customerReference,
|
|
113
|
+
ship_date=tracking.shipDate,
|
|
114
|
+
last_mile_carrier=tracking.lastMile.carrier,
|
|
115
|
+
last_mile_tracking=tracking.lastMile.trackingNumber,
|
|
116
|
+
),
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def verify_webhook_signature(
|
|
121
|
+
payload: models.RequestPayload,
|
|
122
|
+
settings: provider_utils.Settings,
|
|
123
|
+
) -> bool:
|
|
124
|
+
"""Verify the webhook signature using HMAC-SHA256.
|
|
125
|
+
|
|
126
|
+
JavaScript equivalent:
|
|
127
|
+
const crypto = require('crypto');
|
|
128
|
+
|
|
129
|
+
function verifyWebhookSignature(payload, signature, secret) {
|
|
130
|
+
const expectedSignature = crypto
|
|
131
|
+
.createHmac('sha256', secret)
|
|
132
|
+
.update(JSON.stringify(payload))
|
|
133
|
+
.digest('hex');
|
|
134
|
+
|
|
135
|
+
return crypto.timingSafeEqual(
|
|
136
|
+
Buffer.from(signature),
|
|
137
|
+
Buffer.from(expectedSignature)
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
"""
|
|
141
|
+
|
|
142
|
+
# Get the signature from headers (access dict directly - headers contain hyphens)
|
|
143
|
+
headers = payload.headers or {}
|
|
144
|
+
signature = headers.get("x-teleship-signature")
|
|
145
|
+
secret = settings.connection_config.webhook_secret.state
|
|
146
|
+
|
|
147
|
+
# If no signature provided, skip verification (or return False for strict mode)
|
|
148
|
+
if not signature or not secret:
|
|
149
|
+
return True
|
|
150
|
+
|
|
151
|
+
# Compute expected signature using HMAC-SHA256
|
|
152
|
+
# The payload body should be JSON serialized consistently
|
|
153
|
+
payload_bytes = lib.to_json(payload.body).encode("utf-8")
|
|
154
|
+
secret_bytes = secret.encode("utf-8")
|
|
155
|
+
|
|
156
|
+
expected_signature = hmac.new(
|
|
157
|
+
secret_bytes,
|
|
158
|
+
payload_bytes,
|
|
159
|
+
hashlib.sha256,
|
|
160
|
+
).hexdigest()
|
|
161
|
+
|
|
162
|
+
# Use constant-time comparison to prevent timing attacks
|
|
163
|
+
return hmac.compare_digest(signature, expected_signature)
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""Karrio Teleship OAuth processing implementation."""
|
|
2
|
+
|
|
3
|
+
import typing
|
|
4
|
+
import urllib.parse
|
|
5
|
+
import karrio.lib as lib
|
|
6
|
+
import karrio.core.models as models
|
|
7
|
+
import karrio.providers.teleship.error as error
|
|
8
|
+
import karrio.providers.teleship.utils as provider_utils
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def on_oauth_authorize(
|
|
12
|
+
payload: models.OAuthAuthorizePayload,
|
|
13
|
+
settings: provider_utils.Settings,
|
|
14
|
+
) -> typing.Tuple[models.OAuthAuthorizeRequest, typing.List[models.Message]]:
|
|
15
|
+
"""Create OAuth authorize request for Teleship.
|
|
16
|
+
|
|
17
|
+
Generates the authorization URL and parameters needed to initiate
|
|
18
|
+
the OAuth flow with Teleship.
|
|
19
|
+
"""
|
|
20
|
+
messages: typing.List[models.Message] = []
|
|
21
|
+
|
|
22
|
+
# Get OAuth credentials from system config
|
|
23
|
+
scope = payload.options.get("scope", "read_accounts write_shipments")
|
|
24
|
+
|
|
25
|
+
if not settings.oauth_client_id:
|
|
26
|
+
messages.append(
|
|
27
|
+
models.Message(
|
|
28
|
+
carrier_id=settings.carrier_id,
|
|
29
|
+
carrier_name=settings.carrier_name,
|
|
30
|
+
code="OAUTH_CONFIG_ERROR",
|
|
31
|
+
message="TELESHIP_OAUTH_CLIENT_ID is not configured in system settings",
|
|
32
|
+
)
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
# Build authorization URL parameters
|
|
36
|
+
auth_params = dict(
|
|
37
|
+
redirectUri=payload.redirect_uri,
|
|
38
|
+
state=payload.state,
|
|
39
|
+
responseType="code",
|
|
40
|
+
clientId=settings.oauth_client_id,
|
|
41
|
+
scope=scope,
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
authorization_url = lib.identity(
|
|
45
|
+
f"{settings.server_url}/oauth/authorize?{urllib.parse.urlencode(auth_params)}"
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
models.OAuthAuthorizeRequest(
|
|
50
|
+
carrier_name=settings.carrier_name,
|
|
51
|
+
authorization_url=authorization_url,
|
|
52
|
+
meta=dict(scope=scope),
|
|
53
|
+
),
|
|
54
|
+
messages,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def on_oauth_callback(
|
|
59
|
+
payload: models.RequestPayload,
|
|
60
|
+
settings: provider_utils.Settings,
|
|
61
|
+
) -> typing.Tuple[typing.Optional[typing.Dict], typing.List[models.Message]]:
|
|
62
|
+
"""Process OAuth authorization callback.
|
|
63
|
+
|
|
64
|
+
Extracts the authorization code and user credentials from the callback.
|
|
65
|
+
Teleship returns account_client_id and account_client_secret in the callback
|
|
66
|
+
query parameters which are the user's credentials for API access.
|
|
67
|
+
"""
|
|
68
|
+
query = payload.query or {}
|
|
69
|
+
messages = error.parse_error_response(payload.body, settings)
|
|
70
|
+
|
|
71
|
+
code = query.get("code")
|
|
72
|
+
account_client_id = query.get("account_client_id")
|
|
73
|
+
account_client_secret = query.get("account_client_secret")
|
|
74
|
+
|
|
75
|
+
if not code:
|
|
76
|
+
messages.append(
|
|
77
|
+
models.Message(
|
|
78
|
+
carrier_id=settings.carrier_id,
|
|
79
|
+
carrier_name=settings.carrier_name,
|
|
80
|
+
code="OAUTH_CALLBACK_ERROR",
|
|
81
|
+
message="No authorization code received in callback",
|
|
82
|
+
)
|
|
83
|
+
)
|
|
84
|
+
return None, messages
|
|
85
|
+
|
|
86
|
+
if not account_client_id or not account_client_secret:
|
|
87
|
+
messages.append(
|
|
88
|
+
models.Message(
|
|
89
|
+
carrier_id=settings.carrier_id,
|
|
90
|
+
carrier_name=settings.carrier_name,
|
|
91
|
+
code="OAUTH_CALLBACK_ERROR",
|
|
92
|
+
message="Missing account credentials in callback",
|
|
93
|
+
)
|
|
94
|
+
)
|
|
95
|
+
return None, messages
|
|
96
|
+
|
|
97
|
+
# Return credentials that map to the Teleship connection settings
|
|
98
|
+
credentials = dict(
|
|
99
|
+
client_id=account_client_id,
|
|
100
|
+
client_secret=account_client_secret,
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
return credentials, messages
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
"""Karrio Teleship manifest creation implementation."""
|
|
2
|
+
|
|
3
|
+
import typing
|
|
4
|
+
import karrio.schemas.teleship.manifest_request as teleship
|
|
5
|
+
import karrio.schemas.teleship.manifest_response as manifest
|
|
6
|
+
import karrio.lib as lib
|
|
7
|
+
import karrio.core.models as models
|
|
8
|
+
import karrio.providers.teleship.error as error
|
|
9
|
+
import karrio.providers.teleship.utils as provider_utils
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def parse_manifest_response(
|
|
13
|
+
_response: lib.Deserializable[str],
|
|
14
|
+
settings: provider_utils.Settings,
|
|
15
|
+
) -> typing.Tuple[models.ManifestDetails, typing.List[models.Message]]:
|
|
16
|
+
response = _response.deserialize()
|
|
17
|
+
messages = error.parse_error_response(response, settings)
|
|
18
|
+
details = lib.to_object(manifest.ManifestResponseType, response)
|
|
19
|
+
|
|
20
|
+
manifest_details = lib.identity(
|
|
21
|
+
models.ManifestDetails(
|
|
22
|
+
carrier_id=settings.carrier_id,
|
|
23
|
+
carrier_name=settings.carrier_name,
|
|
24
|
+
id=details.id,
|
|
25
|
+
doc=None,
|
|
26
|
+
meta=dict(
|
|
27
|
+
status=details.status,
|
|
28
|
+
reference=details.reference,
|
|
29
|
+
createdAt=details.createdAt,
|
|
30
|
+
),
|
|
31
|
+
)
|
|
32
|
+
if details and details.id
|
|
33
|
+
else None
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
return manifest_details, messages
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def manifest_request(
|
|
40
|
+
payload: models.ManifestRequest,
|
|
41
|
+
settings: provider_utils.Settings,
|
|
42
|
+
) -> lib.Serializable:
|
|
43
|
+
address = lib.to_address(payload.address)
|
|
44
|
+
|
|
45
|
+
request = teleship.ManifestRequestType(
|
|
46
|
+
shipmentIds=payload.shipment_identifiers,
|
|
47
|
+
reference=payload.reference,
|
|
48
|
+
address=lib.identity(
|
|
49
|
+
teleship.ManifestRequestAddressType(
|
|
50
|
+
name=address.person_name,
|
|
51
|
+
email=address.email,
|
|
52
|
+
phone=address.phone_number,
|
|
53
|
+
company=address.company_name,
|
|
54
|
+
address=teleship.AddressAddressType(
|
|
55
|
+
line1=address.address_line1,
|
|
56
|
+
line2=address.address_line2,
|
|
57
|
+
city=address.city,
|
|
58
|
+
state=address.state_code,
|
|
59
|
+
postcode=address.postal_code,
|
|
60
|
+
country=address.country_code,
|
|
61
|
+
),
|
|
62
|
+
)
|
|
63
|
+
if address
|
|
64
|
+
else None
|
|
65
|
+
),
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
return lib.Serializable(request, lib.to_dict)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"""Karrio Teleship pickup cancellation implementation."""
|
|
2
|
+
|
|
3
|
+
import typing
|
|
4
|
+
import karrio.lib as lib
|
|
5
|
+
import karrio.core.models as models
|
|
6
|
+
import karrio.providers.teleship.error as error
|
|
7
|
+
import karrio.providers.teleship.utils as provider_utils
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def parse_cancel_pickup_response(
|
|
11
|
+
_response: lib.Deserializable[str],
|
|
12
|
+
settings: provider_utils.Settings,
|
|
13
|
+
) -> typing.Tuple[models.ConfirmationDetails, typing.List[models.Message]]:
|
|
14
|
+
response = _response.deserialize()
|
|
15
|
+
messages = error.parse_error_response(response, settings)
|
|
16
|
+
|
|
17
|
+
success = not any(messages) and (
|
|
18
|
+
isinstance(response, dict) and response.get("success") is not False
|
|
19
|
+
or response == ""
|
|
20
|
+
or response is None
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
confirmation = (
|
|
24
|
+
models.ConfirmationDetails(
|
|
25
|
+
carrier_id=settings.carrier_id,
|
|
26
|
+
carrier_name=settings.carrier_name,
|
|
27
|
+
success=success,
|
|
28
|
+
operation="pickup_cancellation",
|
|
29
|
+
)
|
|
30
|
+
if success
|
|
31
|
+
else None
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
return confirmation, messages
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def cancel_pickup_request(
|
|
38
|
+
payload: models.PickupCancelRequest,
|
|
39
|
+
settings: provider_utils.Settings,
|
|
40
|
+
) -> lib.Serializable:
|
|
41
|
+
request = {"pickupId": payload.confirmation_number}
|
|
42
|
+
|
|
43
|
+
return lib.Serializable(request, lib.to_dict)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""Karrio Teleship pickup scheduling implementation."""
|
|
2
|
+
|
|
3
|
+
import typing
|
|
4
|
+
import karrio.schemas.teleship.pickup_request as teleship
|
|
5
|
+
import karrio.schemas.teleship.pickup_response as pickup
|
|
6
|
+
import karrio.lib as lib
|
|
7
|
+
import karrio.core.models as models
|
|
8
|
+
import karrio.providers.teleship.error as error
|
|
9
|
+
import karrio.providers.teleship.utils as provider_utils
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def parse_pickup_response(
|
|
13
|
+
_response: lib.Deserializable[str],
|
|
14
|
+
settings: provider_utils.Settings,
|
|
15
|
+
) -> typing.Tuple[models.PickupDetails, typing.List[models.Message]]:
|
|
16
|
+
response = _response.deserialize()
|
|
17
|
+
messages = error.parse_error_response(response, settings)
|
|
18
|
+
details = lib.to_object(pickup.PickupResponseType, response)
|
|
19
|
+
|
|
20
|
+
pickup_details = lib.identity(
|
|
21
|
+
models.PickupDetails(
|
|
22
|
+
carrier_id=settings.carrier_id,
|
|
23
|
+
carrier_name=settings.carrier_name,
|
|
24
|
+
confirmation_number=details.pickup.id,
|
|
25
|
+
pickup_date=lib.fdatetime(
|
|
26
|
+
details.pickup.startAt,
|
|
27
|
+
current_format="%Y-%m-%dT%H:%M:%S.%fZ",
|
|
28
|
+
output_format="%Y-%m-%d",
|
|
29
|
+
),
|
|
30
|
+
meta=lib.to_dict(details.pickup),
|
|
31
|
+
)
|
|
32
|
+
if details and details.pickup and details.pickup.id
|
|
33
|
+
else None
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
return pickup_details, messages
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def pickup_request(
|
|
40
|
+
payload: models.PickupRequest,
|
|
41
|
+
settings: provider_utils.Settings,
|
|
42
|
+
) -> lib.Serializable:
|
|
43
|
+
address = lib.to_address(payload.address)
|
|
44
|
+
|
|
45
|
+
request = teleship.PickupRequestType(
|
|
46
|
+
startAt=payload.pickup_date,
|
|
47
|
+
endAt=payload.closing_time or payload.pickup_date,
|
|
48
|
+
shipmentIds=payload.shipment_identifiers,
|
|
49
|
+
address=teleship.PickupRequestAddressType(
|
|
50
|
+
name=address.person_name,
|
|
51
|
+
email=address.email,
|
|
52
|
+
phone=address.phone_number,
|
|
53
|
+
company=address.company_name,
|
|
54
|
+
address=teleship.AddressAddressType(
|
|
55
|
+
line1=address.address_line1,
|
|
56
|
+
line2=address.address_line2,
|
|
57
|
+
city=address.city,
|
|
58
|
+
state=address.state_code,
|
|
59
|
+
postcode=address.postal_code,
|
|
60
|
+
country=address.country_code,
|
|
61
|
+
),
|
|
62
|
+
),
|
|
63
|
+
reference=payload.instruction,
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
return lib.Serializable(request, lib.to_dict)
|