karrio-canadapost 2025.5rc1__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/canadapost/__init__.py +3 -0
- karrio/mappers/canadapost/mapper.py +88 -0
- karrio/mappers/canadapost/proxy.py +373 -0
- karrio/mappers/canadapost/settings.py +23 -0
- karrio/plugins/canadapost/__init__.py +23 -0
- karrio/providers/canadapost/__init__.py +25 -0
- karrio/providers/canadapost/error.py +42 -0
- karrio/providers/canadapost/manifest.py +127 -0
- karrio/providers/canadapost/pickup/__init__.py +3 -0
- karrio/providers/canadapost/pickup/cancel.py +33 -0
- karrio/providers/canadapost/pickup/create.py +217 -0
- karrio/providers/canadapost/pickup/update.py +55 -0
- karrio/providers/canadapost/rate.py +192 -0
- karrio/providers/canadapost/shipment/__init__.py +8 -0
- karrio/providers/canadapost/shipment/cancel.py +53 -0
- karrio/providers/canadapost/shipment/create.py +308 -0
- karrio/providers/canadapost/tracking.py +75 -0
- karrio/providers/canadapost/units.py +285 -0
- karrio/providers/canadapost/utils.py +92 -0
- karrio/schemas/canadapost/__init__.py +0 -0
- karrio/schemas/canadapost/authreturn.py +3389 -0
- karrio/schemas/canadapost/common.py +2037 -0
- karrio/schemas/canadapost/customerinfo.py +2307 -0
- karrio/schemas/canadapost/discovery.py +3016 -0
- karrio/schemas/canadapost/manifest.py +3704 -0
- karrio/schemas/canadapost/merchantregistration.py +1498 -0
- karrio/schemas/canadapost/messages.py +1431 -0
- karrio/schemas/canadapost/ncshipment.py +7231 -0
- karrio/schemas/canadapost/openreturn.py +2438 -0
- karrio/schemas/canadapost/pickup.py +1407 -0
- karrio/schemas/canadapost/pickuprequest.py +6794 -0
- karrio/schemas/canadapost/postoffice.py +2240 -0
- karrio/schemas/canadapost/rating.py +5308 -0
- karrio/schemas/canadapost/serviceinfo.py +1505 -0
- karrio/schemas/canadapost/shipment.py +9982 -0
- karrio/schemas/canadapost/track.py +3100 -0
- karrio_canadapost-2025.5rc1.dist-info/METADATA +44 -0
- karrio_canadapost-2025.5rc1.dist-info/RECORD +41 -0
- karrio_canadapost-2025.5rc1.dist-info/WHEEL +5 -0
- karrio_canadapost-2025.5rc1.dist-info/entry_points.txt +2 -0
- karrio_canadapost-2025.5rc1.dist-info/top_level.txt +3 -0
@@ -0,0 +1,308 @@
|
|
1
|
+
import karrio.schemas.canadapost.shipment as canadapost
|
2
|
+
import uuid
|
3
|
+
import typing
|
4
|
+
import datetime
|
5
|
+
import karrio.lib as lib
|
6
|
+
import karrio.core.units as units
|
7
|
+
import karrio.core.models as models
|
8
|
+
import karrio.providers.canadapost.error as provider_error
|
9
|
+
import karrio.providers.canadapost.units as provider_units
|
10
|
+
import karrio.providers.canadapost.utils as provider_utils
|
11
|
+
|
12
|
+
|
13
|
+
def parse_shipment_response(
|
14
|
+
_responses: lib.Deserializable[typing.Tuple[lib.Element, str]],
|
15
|
+
settings: provider_utils.Settings,
|
16
|
+
) -> typing.Tuple[models.ShipmentDetails, typing.List[models.Message]]:
|
17
|
+
responses = _responses.deserialize()
|
18
|
+
|
19
|
+
shipment_details = [
|
20
|
+
(
|
21
|
+
f"{_}",
|
22
|
+
(
|
23
|
+
_extract_shipment(response, settings, _responses.ctx)
|
24
|
+
if len(lib.find_element("shipment-id", response[0])) > 0
|
25
|
+
else None
|
26
|
+
),
|
27
|
+
)
|
28
|
+
for _, response in enumerate(responses, start=1)
|
29
|
+
]
|
30
|
+
|
31
|
+
shipment = lib.to_multi_piece_shipment(shipment_details)
|
32
|
+
messages: typing.List[models.Message] = sum(
|
33
|
+
[provider_error.parse_error_response(_, settings) for _, __ in responses],
|
34
|
+
start=[],
|
35
|
+
)
|
36
|
+
|
37
|
+
return shipment, messages
|
38
|
+
|
39
|
+
|
40
|
+
def _extract_shipment(
|
41
|
+
_response: typing.Tuple[lib.Element, str],
|
42
|
+
settings: provider_utils.Settings,
|
43
|
+
ctx: dict,
|
44
|
+
) -> models.ShipmentDetails:
|
45
|
+
response, label = _response
|
46
|
+
info = lib.to_object(canadapost.ShipmentInfoType, response)
|
47
|
+
|
48
|
+
return models.ShipmentDetails(
|
49
|
+
carrier_name=settings.carrier_name,
|
50
|
+
carrier_id=settings.carrier_id,
|
51
|
+
tracking_number=info.tracking_pin,
|
52
|
+
shipment_identifier=info.shipment_id,
|
53
|
+
docs=models.Documents(label=label),
|
54
|
+
label_type=ctx["label_type"],
|
55
|
+
meta=lib.to_dict(
|
56
|
+
dict(
|
57
|
+
carrier_tracking_link=settings.tracking_url.format(info.tracking_pin),
|
58
|
+
customer_request_ids=ctx["customer_request_ids"],
|
59
|
+
manifest_required=ctx["manifest_required"],
|
60
|
+
group_id=ctx["group_id"],
|
61
|
+
)
|
62
|
+
),
|
63
|
+
)
|
64
|
+
|
65
|
+
|
66
|
+
def shipment_request(
|
67
|
+
payload: models.ShipmentRequest,
|
68
|
+
settings: provider_utils.Settings,
|
69
|
+
) -> lib.Serializable:
|
70
|
+
shipper = lib.to_address(payload.shipper)
|
71
|
+
recipient = lib.to_address(payload.recipient)
|
72
|
+
service = provider_units.ServiceType.map(payload.service).value_or_key
|
73
|
+
options = lib.to_shipping_options(
|
74
|
+
payload.options,
|
75
|
+
is_international=(
|
76
|
+
recipient.country_code is not None and recipient.country_code != "CA"
|
77
|
+
),
|
78
|
+
initializer=provider_units.shipping_options_initializer,
|
79
|
+
)
|
80
|
+
packages = lib.to_packages(
|
81
|
+
payload.parcels,
|
82
|
+
provider_units.PackagePresets,
|
83
|
+
required=["weight"],
|
84
|
+
options=options,
|
85
|
+
package_option_type=provider_units.ShippingOption,
|
86
|
+
shipping_options_initializer=provider_units.shipping_options_initializer,
|
87
|
+
)
|
88
|
+
|
89
|
+
customs = lib.to_customs_info(payload.customs, weight_unit=units.WeightUnit.KG.name)
|
90
|
+
label_encoding, label_format = provider_units.LabelType.map(
|
91
|
+
payload.label_type or "PDF_4x6"
|
92
|
+
).value
|
93
|
+
group_id = lib.fdate(datetime.datetime.now(), "%Y%m%d") + "-" + settings.carrier_id
|
94
|
+
customer_request_ids = [f"{str(uuid.uuid4().hex)}" for _ in range(len(packages))]
|
95
|
+
submit_shipment = lib.identity(
|
96
|
+
# set to true if canadapost_submit_shipment is true
|
97
|
+
options.canadapost_submit_shipment.state
|
98
|
+
# default to true if transmit_shipment_by_default is true
|
99
|
+
or (
|
100
|
+
settings.connection_config.transmit_shipment_by_default.state
|
101
|
+
and options.canadapost_submit_shipment.state is not False
|
102
|
+
)
|
103
|
+
)
|
104
|
+
|
105
|
+
requests = [
|
106
|
+
canadapost.ShipmentType(
|
107
|
+
customer_request_id=customer_request_ids[index],
|
108
|
+
groupIdOrTransmitShipment=canadapost.groupIdOrTransmitShipment(),
|
109
|
+
quickship_label_requested=None,
|
110
|
+
cpc_pickup_indicator=None,
|
111
|
+
requested_shipping_point=provider_utils.format_ca_postal_code(
|
112
|
+
shipper.postal_code
|
113
|
+
),
|
114
|
+
shipping_point_id=None,
|
115
|
+
expected_mailing_date=options.shipment_date.state,
|
116
|
+
provide_pricing_info=True,
|
117
|
+
provide_receipt_info=None,
|
118
|
+
delivery_spec=canadapost.DeliverySpecType(
|
119
|
+
service_code=service,
|
120
|
+
sender=canadapost.SenderType(
|
121
|
+
name=shipper.person_name,
|
122
|
+
company=(shipper.company_name or "Not Applicable"),
|
123
|
+
contact_phone=(shipper.phone_number or "000 000 0000"),
|
124
|
+
address_details=canadapost.AddressDetailsType(
|
125
|
+
city=shipper.city,
|
126
|
+
prov_state=shipper.state_code,
|
127
|
+
country_code=shipper.country_code,
|
128
|
+
postal_zip_code=provider_utils.format_ca_postal_code(
|
129
|
+
shipper.postal_code
|
130
|
+
),
|
131
|
+
address_line_1=shipper.street,
|
132
|
+
address_line_2=lib.text(shipper.address_line2),
|
133
|
+
),
|
134
|
+
),
|
135
|
+
destination=canadapost.DestinationType(
|
136
|
+
name=recipient.person_name,
|
137
|
+
company=recipient.company_name,
|
138
|
+
additional_address_info=None,
|
139
|
+
client_voice_number=recipient.phone_number or "000 000 0000",
|
140
|
+
address_details=canadapost.DestinationAddressDetailsType(
|
141
|
+
city=recipient.city,
|
142
|
+
prov_state=recipient.state_code,
|
143
|
+
country_code=recipient.country_code,
|
144
|
+
postal_zip_code=provider_utils.format_ca_postal_code(
|
145
|
+
recipient.postal_code
|
146
|
+
),
|
147
|
+
address_line_1=recipient.street,
|
148
|
+
address_line_2=lib.text(recipient.address_line2),
|
149
|
+
),
|
150
|
+
),
|
151
|
+
parcel_characteristics=canadapost.ParcelCharacteristicsType(
|
152
|
+
weight=package.weight.map(provider_units.MeasurementOptions).KG,
|
153
|
+
dimensions=canadapost.dimensionsType(
|
154
|
+
length=package.length.map(provider_units.MeasurementOptions).CM,
|
155
|
+
width=package.width.map(provider_units.MeasurementOptions).CM,
|
156
|
+
height=package.height.map(provider_units.MeasurementOptions).CM,
|
157
|
+
),
|
158
|
+
unpackaged=None,
|
159
|
+
mailing_tube=None,
|
160
|
+
),
|
161
|
+
options=(
|
162
|
+
canadapost.optionsType(
|
163
|
+
option=[
|
164
|
+
canadapost.OptionType(
|
165
|
+
option_code=option.code,
|
166
|
+
option_amount=lib.to_money(option.state),
|
167
|
+
option_qualifier_1=None,
|
168
|
+
option_qualifier_2=None,
|
169
|
+
)
|
170
|
+
for _, option in package.options.items()
|
171
|
+
if option.state is not False
|
172
|
+
]
|
173
|
+
)
|
174
|
+
if any(
|
175
|
+
[
|
176
|
+
option
|
177
|
+
for _, option in package.options.items()
|
178
|
+
if option.state is not False
|
179
|
+
]
|
180
|
+
)
|
181
|
+
else None
|
182
|
+
),
|
183
|
+
notification=(
|
184
|
+
canadapost.NotificationType(
|
185
|
+
email=(
|
186
|
+
package.options.email_notification_to.state
|
187
|
+
or recipient.email
|
188
|
+
),
|
189
|
+
on_shipment=True,
|
190
|
+
on_exception=True,
|
191
|
+
on_delivery=True,
|
192
|
+
)
|
193
|
+
if package.options.email_notification.state
|
194
|
+
and any(
|
195
|
+
[package.options.email_notification_to.state, recipient.email]
|
196
|
+
)
|
197
|
+
else None
|
198
|
+
),
|
199
|
+
print_preferences=canadapost.PrintPreferencesType(
|
200
|
+
output_format=label_format,
|
201
|
+
encoding=label_encoding,
|
202
|
+
),
|
203
|
+
preferences=canadapost.PreferencesType(
|
204
|
+
service_code=None,
|
205
|
+
show_packing_instructions=False,
|
206
|
+
show_postage_rate=True,
|
207
|
+
show_insured_value=True,
|
208
|
+
),
|
209
|
+
customs=(
|
210
|
+
canadapost.CustomsType(
|
211
|
+
currency=(options.currency.state or units.Currency.CAD.name),
|
212
|
+
conversion_from_cad=None,
|
213
|
+
reason_for_export="OTH",
|
214
|
+
other_reason=customs.content_type,
|
215
|
+
duties_and_taxes_prepaid=customs.duty.account_number,
|
216
|
+
certificate_number=customs.options.certificate_number.state,
|
217
|
+
licence_number=lib.text(
|
218
|
+
customs.options.license_number.state, max=10
|
219
|
+
),
|
220
|
+
invoice_number=lib.text(customs.invoice, max=10),
|
221
|
+
sku_list=(
|
222
|
+
(
|
223
|
+
canadapost.sku_listType(
|
224
|
+
item=[
|
225
|
+
canadapost.SkuType(
|
226
|
+
customs_number_of_units=item.quantity,
|
227
|
+
customs_description=lib.text(
|
228
|
+
item.title
|
229
|
+
or item.description
|
230
|
+
or item.sku
|
231
|
+
or "N/B",
|
232
|
+
max=35,
|
233
|
+
),
|
234
|
+
sku=item.sku or "0000",
|
235
|
+
hs_tariff_code=item.hs_code,
|
236
|
+
unit_weight=(item.weight or 1),
|
237
|
+
customs_value_per_unit=item.value_amount,
|
238
|
+
customs_unit_of_measure=None,
|
239
|
+
country_of_origin=(
|
240
|
+
item.origin_country
|
241
|
+
or shipper.country_code
|
242
|
+
),
|
243
|
+
province_of_origin=shipper.state_code
|
244
|
+
or "N/B",
|
245
|
+
)
|
246
|
+
for item in customs.commodities
|
247
|
+
]
|
248
|
+
)
|
249
|
+
)
|
250
|
+
if any(customs.commodities or [])
|
251
|
+
else None
|
252
|
+
),
|
253
|
+
)
|
254
|
+
if payload.customs is not None
|
255
|
+
else None
|
256
|
+
),
|
257
|
+
references=canadapost.ReferencesType(
|
258
|
+
cost_centre=(
|
259
|
+
options.canadapost_cost_center.state
|
260
|
+
or settings.connection_config.cost_center.state
|
261
|
+
or payload.reference
|
262
|
+
),
|
263
|
+
customer_ref_1=payload.reference,
|
264
|
+
customer_ref_2=None,
|
265
|
+
),
|
266
|
+
settlement_info=canadapost.SettlementInfoType(
|
267
|
+
paid_by_customer=getattr(
|
268
|
+
payload.payment, "account_number", settings.customer_number
|
269
|
+
),
|
270
|
+
contract_id=settings.contract_id,
|
271
|
+
cif_shipment=None,
|
272
|
+
intended_method_of_payment=provider_units.PaymentType.map(
|
273
|
+
getattr(payload.payment, "paid_by", None)
|
274
|
+
).value,
|
275
|
+
promo_code=None,
|
276
|
+
),
|
277
|
+
),
|
278
|
+
return_spec=None,
|
279
|
+
pre_authorized_payment=None,
|
280
|
+
create_qr_code=None,
|
281
|
+
)
|
282
|
+
for index, package in enumerate(packages)
|
283
|
+
]
|
284
|
+
|
285
|
+
return lib.Serializable(
|
286
|
+
requests,
|
287
|
+
lambda __: [
|
288
|
+
lib.to_xml(
|
289
|
+
request,
|
290
|
+
name_="shipment",
|
291
|
+
namespacedef_='xmlns="http://www.canadapost.ca/ws/shipment-v8"',
|
292
|
+
).replace(
|
293
|
+
"<groupIdOrTransmitShipment/>",
|
294
|
+
(
|
295
|
+
"<transmit-shipment/>"
|
296
|
+
if submit_shipment
|
297
|
+
else f"<group-id>{group_id}</group-id>"
|
298
|
+
),
|
299
|
+
)
|
300
|
+
for request in __
|
301
|
+
],
|
302
|
+
dict(
|
303
|
+
label_type=label_encoding,
|
304
|
+
manifest_required=(not submit_shipment),
|
305
|
+
customer_request_ids=customer_request_ids,
|
306
|
+
group_id=(None if submit_shipment else group_id),
|
307
|
+
),
|
308
|
+
)
|
@@ -0,0 +1,75 @@
|
|
1
|
+
import karrio.schemas.canadapost.track as capost
|
2
|
+
import typing
|
3
|
+
import karrio.lib as lib
|
4
|
+
import karrio.core.models as models
|
5
|
+
import karrio.providers.canadapost.error as error
|
6
|
+
import karrio.providers.canadapost.units as provider_units
|
7
|
+
import karrio.providers.canadapost.utils as provider_utils
|
8
|
+
|
9
|
+
|
10
|
+
def parse_tracking_response(
|
11
|
+
_response: lib.Deserializable[lib.Element],
|
12
|
+
settings: provider_utils.Settings,
|
13
|
+
) -> typing.Tuple[typing.List[models.TrackingDetails], typing.List[models.Message]]:
|
14
|
+
response = _response.deserialize()
|
15
|
+
details = lib.find_element("tracking-detail", response)
|
16
|
+
tracking_details: typing.List[models.TrackingDetails] = [
|
17
|
+
_extract_tracking(node, settings)
|
18
|
+
for node in details
|
19
|
+
if len(lib.find_element("occurrence", node)) > 0
|
20
|
+
]
|
21
|
+
|
22
|
+
return tracking_details, error.parse_error_response(response, settings)
|
23
|
+
|
24
|
+
|
25
|
+
def _extract_tracking(
|
26
|
+
detail_node: lib.Element,
|
27
|
+
settings: provider_utils.Settings,
|
28
|
+
) -> models.TrackingDetails:
|
29
|
+
details = lib.to_object(capost.tracking_detail, detail_node)
|
30
|
+
events: typing.List[capost.occurrenceType] = details.significant_events.occurrence
|
31
|
+
last_event = events[0]
|
32
|
+
estimated_delivery = lib.fdate(
|
33
|
+
details.changed_expected_date or details.expected_delivery_date,
|
34
|
+
"%Y-%m-%d",
|
35
|
+
)
|
36
|
+
status = next(
|
37
|
+
(
|
38
|
+
status.name
|
39
|
+
for status in list(provider_units.TrackingStatus)
|
40
|
+
if last_event.event_identifier in status.value
|
41
|
+
),
|
42
|
+
provider_units.TrackingStatus.in_transit.name,
|
43
|
+
)
|
44
|
+
|
45
|
+
return models.TrackingDetails(
|
46
|
+
carrier_name=settings.carrier_name,
|
47
|
+
carrier_id=settings.carrier_id,
|
48
|
+
tracking_number=details.pin,
|
49
|
+
estimated_delivery=estimated_delivery,
|
50
|
+
delivered=status == "delivered",
|
51
|
+
status=status,
|
52
|
+
events=[
|
53
|
+
models.TrackingEvent(
|
54
|
+
date=lib.fdate(event.event_date, "%Y-%m-%d"),
|
55
|
+
time=lib.flocaltime(event.event_time, "%H:%M:%S"),
|
56
|
+
code=event.event_identifier,
|
57
|
+
location=lib.join(
|
58
|
+
event.event_site, event.event_province, join=True, separator=", "
|
59
|
+
),
|
60
|
+
description=event.event_description,
|
61
|
+
)
|
62
|
+
for event in events
|
63
|
+
],
|
64
|
+
info=models.TrackingInfo(
|
65
|
+
carrier_tracking_link=settings.tracking_url.format(details.pin),
|
66
|
+
shipment_destination_postal_code=details.destination_postal_id,
|
67
|
+
shipment_delivery_date=estimated_delivery,
|
68
|
+
shipment_service=details.service_name,
|
69
|
+
signed_by=last_event.signatory_name,
|
70
|
+
),
|
71
|
+
)
|
72
|
+
|
73
|
+
|
74
|
+
def tracking_request(payload: models.TrackingRequest, _) -> lib.Serializable:
|
75
|
+
return lib.Serializable(payload.tracking_numbers)
|
@@ -0,0 +1,285 @@
|
|
1
|
+
import karrio.lib as lib
|
2
|
+
|
3
|
+
PRESET_DEFAULTS = dict(
|
4
|
+
dimension_unit="CM",
|
5
|
+
weight_unit="KG",
|
6
|
+
)
|
7
|
+
|
8
|
+
MeasurementOptions = lib.units.MeasurementOptionsType(
|
9
|
+
quant=0.1,
|
10
|
+
min_kg=0.01,
|
11
|
+
min_in=0.01,
|
12
|
+
)
|
13
|
+
|
14
|
+
|
15
|
+
class PackagePresets(lib.Enum):
|
16
|
+
"""
|
17
|
+
Note that dimensions are in CM and weight in KG
|
18
|
+
"""
|
19
|
+
|
20
|
+
canadapost_mailing_box = lib.units.PackagePreset(
|
21
|
+
**dict(width=10.2, height=15.2, length=1.0), **PRESET_DEFAULTS
|
22
|
+
)
|
23
|
+
canadapost_extra_small_mailing_box = lib.units.PackagePreset(
|
24
|
+
**dict(width=14.0, height=14.0, length=14.0), **PRESET_DEFAULTS
|
25
|
+
)
|
26
|
+
canadapost_small_mailing_box = lib.units.PackagePreset(
|
27
|
+
**dict(width=28.6, height=22.9, length=6.4), **PRESET_DEFAULTS
|
28
|
+
)
|
29
|
+
canadapost_medium_mailing_box = lib.units.PackagePreset(
|
30
|
+
**dict(width=31.0, height=23.5, length=13.3), **PRESET_DEFAULTS
|
31
|
+
)
|
32
|
+
canadapost_large_mailing_box = lib.units.PackagePreset(
|
33
|
+
**dict(width=38.1, height=30.5, length=9.5), **PRESET_DEFAULTS
|
34
|
+
)
|
35
|
+
canadapost_extra_large_mailing_box = lib.units.PackagePreset(
|
36
|
+
**dict(width=40.0, height=30.5, length=21.6), **PRESET_DEFAULTS
|
37
|
+
)
|
38
|
+
canadapost_corrugated_small_box = lib.units.PackagePreset(
|
39
|
+
**dict(width=42.0, height=32.0, length=32.0), **PRESET_DEFAULTS
|
40
|
+
)
|
41
|
+
canadapost_corrugated_medium_box = lib.units.PackagePreset(
|
42
|
+
**dict(width=46.0, height=38.0, length=32.0), **PRESET_DEFAULTS
|
43
|
+
)
|
44
|
+
canadapost_corrugated_large_box = lib.units.PackagePreset(
|
45
|
+
**dict(width=46.0, height=46.0, length=40.6), **PRESET_DEFAULTS
|
46
|
+
)
|
47
|
+
canadapost_xexpresspost_certified_envelope = lib.units.PackagePreset(
|
48
|
+
**dict(width=26.0, height=15.9, weight=0.5, length=1.5), **PRESET_DEFAULTS
|
49
|
+
)
|
50
|
+
canadapost_xexpresspost_national_large_envelope = lib.units.PackagePreset(
|
51
|
+
**dict(width=40.0, height=29.2, weight=1.36, length=1.5), **PRESET_DEFAULTS
|
52
|
+
)
|
53
|
+
canadapost_xexpresspost_regional_small_envelope = lib.units.PackagePreset(
|
54
|
+
**dict(width=26.0, height=15.9, weight=0.5, length=1.5), **PRESET_DEFAULTS
|
55
|
+
)
|
56
|
+
canadapost_xexpresspost_regional_large_envelope = lib.units.PackagePreset(
|
57
|
+
**dict(width=40.0, height=29.2, weight=1.36, length=1.5), **PRESET_DEFAULTS
|
58
|
+
)
|
59
|
+
|
60
|
+
|
61
|
+
class LabelType(lib.Enum):
|
62
|
+
PDF_4x6 = ("PDF", "4x6")
|
63
|
+
PDF_8_5x11 = ("PDF", "8.5x11")
|
64
|
+
ZPL_4x6 = ("ZPL", "4x6")
|
65
|
+
|
66
|
+
""" Unified Label type mapping """
|
67
|
+
PDF = PDF_4x6
|
68
|
+
ZPL = ZPL_4x6
|
69
|
+
|
70
|
+
|
71
|
+
class PaymentType(lib.StrEnum):
|
72
|
+
account = "Account"
|
73
|
+
card = "CreditCard"
|
74
|
+
supplier_account = "SupplierAccount"
|
75
|
+
|
76
|
+
sender = account
|
77
|
+
recipient = account
|
78
|
+
third_party = supplier_account
|
79
|
+
credit_card = card
|
80
|
+
|
81
|
+
|
82
|
+
class ConnectionConfig(lib.Enum):
|
83
|
+
cost_center = lib.OptionEnum("cost_center")
|
84
|
+
label_type = lib.OptionEnum("label_type", LabelType)
|
85
|
+
shipping_options = lib.OptionEnum("shipping_options", list)
|
86
|
+
shipping_services = lib.OptionEnum("shipping_services", list)
|
87
|
+
transmit_shipment_by_default = lib.OptionEnum("transmit_shipment_by_default", bool)
|
88
|
+
|
89
|
+
|
90
|
+
class ServiceType(lib.Enum):
|
91
|
+
canadapost_regular_parcel = "DOM.RP"
|
92
|
+
canadapost_expedited_parcel = "DOM.EP"
|
93
|
+
canadapost_xpresspost = "DOM.XP"
|
94
|
+
canadapost_xpresspost_certified = "DOM.XP.CERT"
|
95
|
+
canadapost_priority = "DOM.PC"
|
96
|
+
canadapost_library_books = "DOM.LIB"
|
97
|
+
canadapost_expedited_parcel_usa = "USA.EP"
|
98
|
+
canadapost_priority_worldwide_envelope_usa = "USA.PW.ENV"
|
99
|
+
canadapost_priority_worldwide_pak_usa = "USA.PW.PAK"
|
100
|
+
canadapost_priority_worldwide_parcel_usa = "USA.PW.PARCEL"
|
101
|
+
canadapost_small_packet_usa_air = "USA.SP.AIR"
|
102
|
+
canadapost_tracked_packet_usa = "USA.TP"
|
103
|
+
canadapost_tracked_packet_usa_lvm = "USA.TP.LVM"
|
104
|
+
canadapost_xpresspost_usa = "USA.XP"
|
105
|
+
canadapost_xpresspost_international = "INT.XP"
|
106
|
+
canadapost_international_parcel_air = "INT.IP.AIR"
|
107
|
+
canadapost_international_parcel_surface = "INT.IP.SURF"
|
108
|
+
canadapost_priority_worldwide_envelope_intl = "INT.PW.ENV"
|
109
|
+
canadapost_priority_worldwide_pak_intl = "INT.PW.PAK"
|
110
|
+
canadapost_priority_worldwide_parcel_intl = "INT.PW.PARCEL"
|
111
|
+
canadapost_small_packet_international_air = "INT.SP.AIR"
|
112
|
+
canadapost_small_packet_international_surface = "INT.SP.SURF"
|
113
|
+
canadapost_tracked_packet_international = "INT.TP"
|
114
|
+
|
115
|
+
|
116
|
+
class ShippingOption(lib.Enum):
|
117
|
+
canadapost_signature = lib.OptionEnum("SO", bool)
|
118
|
+
canadapost_coverage = lib.OptionEnum("COV", float)
|
119
|
+
canadapost_collect_on_delivery = lib.OptionEnum("COD", float)
|
120
|
+
canadapost_proof_of_age_required_18 = lib.OptionEnum("PA18", bool)
|
121
|
+
canadapost_proof_of_age_required_19 = lib.OptionEnum("PA19", bool)
|
122
|
+
canadapost_card_for_pickup = lib.OptionEnum("HFP", bool)
|
123
|
+
canadapost_do_not_safe_drop = lib.OptionEnum("DNS", bool)
|
124
|
+
canadapost_leave_at_door = lib.OptionEnum("LAD", bool)
|
125
|
+
canadapost_deliver_to_post_office = lib.OptionEnum("D2PO", bool)
|
126
|
+
canadapost_return_at_senders_expense = lib.OptionEnum("RASE", bool)
|
127
|
+
canadapost_return_to_sender = lib.OptionEnum("RTS", bool)
|
128
|
+
canadapost_abandon = lib.OptionEnum("ABAN", bool)
|
129
|
+
|
130
|
+
""" Custom Option """
|
131
|
+
canadapost_cost_center = lib.OptionEnum("cost-centre")
|
132
|
+
canadapost_submit_shipment = lib.OptionEnum("transmit-shipment", bool)
|
133
|
+
|
134
|
+
""" Unified Option type mapping """
|
135
|
+
insurance = canadapost_coverage
|
136
|
+
cash_on_delivery = canadapost_collect_on_delivery
|
137
|
+
signature_confirmation = canadapost_signature
|
138
|
+
|
139
|
+
|
140
|
+
def shipping_options_initializer(
|
141
|
+
options: dict,
|
142
|
+
package_options: lib.units.ShippingOptions = None,
|
143
|
+
is_international: bool = False,
|
144
|
+
) -> lib.units.ShippingOptions:
|
145
|
+
_options = options.copy()
|
146
|
+
|
147
|
+
# Apply default non delivery options for if international.
|
148
|
+
no_international_option_specified: bool = not any(
|
149
|
+
key in _options for key in INTERNATIONAL_NON_DELIVERY_OPTION
|
150
|
+
)
|
151
|
+
|
152
|
+
if is_international and no_international_option_specified:
|
153
|
+
_options.update(
|
154
|
+
{ShippingOption.canadapost_return_at_senders_expense.name: True}
|
155
|
+
)
|
156
|
+
|
157
|
+
# Apply package options if specified.
|
158
|
+
if package_options is not None:
|
159
|
+
_options.update(package_options.content)
|
160
|
+
|
161
|
+
# Define carrier option filter.
|
162
|
+
def items_filter(key: str) -> bool:
|
163
|
+
return key in ShippingOption and key not in CUSTOM_OPTIONS # type:ignore
|
164
|
+
|
165
|
+
return lib.units.ShippingOptions(
|
166
|
+
_options, ShippingOption, items_filter=items_filter
|
167
|
+
)
|
168
|
+
|
169
|
+
|
170
|
+
class TrackingStatus(lib.Enum):
|
171
|
+
"""Carrier tracking status mapping"""
|
172
|
+
|
173
|
+
delivered = [
|
174
|
+
"1408",
|
175
|
+
"1409",
|
176
|
+
"1421",
|
177
|
+
"1422",
|
178
|
+
"1423",
|
179
|
+
"1424",
|
180
|
+
"1425",
|
181
|
+
"1426",
|
182
|
+
"1427",
|
183
|
+
"1428",
|
184
|
+
"1429",
|
185
|
+
"1430",
|
186
|
+
"1431",
|
187
|
+
"1432",
|
188
|
+
"1433",
|
189
|
+
"1434",
|
190
|
+
"1441",
|
191
|
+
"1442",
|
192
|
+
"1496",
|
193
|
+
"1497",
|
194
|
+
"1498",
|
195
|
+
"1499",
|
196
|
+
]
|
197
|
+
in_transit = [""]
|
198
|
+
on_hold = [
|
199
|
+
"117",
|
200
|
+
"120",
|
201
|
+
"121",
|
202
|
+
"125",
|
203
|
+
"127",
|
204
|
+
"810",
|
205
|
+
"1411",
|
206
|
+
"1414",
|
207
|
+
"1443",
|
208
|
+
"1484",
|
209
|
+
"1487",
|
210
|
+
"1494",
|
211
|
+
"2411",
|
212
|
+
"2414",
|
213
|
+
"4700",
|
214
|
+
]
|
215
|
+
ready_for_pickup = [
|
216
|
+
"118",
|
217
|
+
"156",
|
218
|
+
"1407",
|
219
|
+
"1410",
|
220
|
+
"1435",
|
221
|
+
"1436",
|
222
|
+
"1437",
|
223
|
+
"1438",
|
224
|
+
"1479",
|
225
|
+
"1488",
|
226
|
+
"1701",
|
227
|
+
"2410",
|
228
|
+
]
|
229
|
+
delivery_failed = [
|
230
|
+
"150",
|
231
|
+
"154",
|
232
|
+
"167",
|
233
|
+
"168",
|
234
|
+
"169",
|
235
|
+
"167",
|
236
|
+
"168",
|
237
|
+
"169",
|
238
|
+
"179",
|
239
|
+
"181",
|
240
|
+
"182",
|
241
|
+
"183",
|
242
|
+
"184",
|
243
|
+
"190",
|
244
|
+
"1100",
|
245
|
+
"1415",
|
246
|
+
"1416",
|
247
|
+
"1417",
|
248
|
+
"1418",
|
249
|
+
"1419",
|
250
|
+
"1420",
|
251
|
+
"1450",
|
252
|
+
"1481",
|
253
|
+
"1482",
|
254
|
+
"1483",
|
255
|
+
"1491",
|
256
|
+
"1492",
|
257
|
+
"1493",
|
258
|
+
"2600",
|
259
|
+
"2802",
|
260
|
+
"3001",
|
261
|
+
"4650",
|
262
|
+
]
|
263
|
+
delivery_delayed = [
|
264
|
+
"159",
|
265
|
+
"160",
|
266
|
+
"161",
|
267
|
+
"162",
|
268
|
+
"163",
|
269
|
+
"172",
|
270
|
+
"173",
|
271
|
+
"2412",
|
272
|
+
]
|
273
|
+
out_for_delivery = ["174", "500"]
|
274
|
+
|
275
|
+
|
276
|
+
INTERNATIONAL_NON_DELIVERY_OPTION = [
|
277
|
+
ShippingOption.canadapost_return_at_senders_expense.name,
|
278
|
+
ShippingOption.canadapost_return_to_sender.name,
|
279
|
+
ShippingOption.canadapost_abandon.name,
|
280
|
+
]
|
281
|
+
|
282
|
+
CUSTOM_OPTIONS = [
|
283
|
+
ShippingOption.canadapost_cost_center.name,
|
284
|
+
ShippingOption.canadapost_submit_shipment.name,
|
285
|
+
]
|