karrio-australiapost 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/australiapost/__init__.py +3 -0
- karrio/mappers/australiapost/mapper.py +60 -0
- karrio/mappers/australiapost/proxy.py +151 -0
- karrio/mappers/australiapost/settings.py +22 -0
- karrio/plugins/australiapost/__init__.py +23 -0
- karrio/providers/australiapost/__init__.py +16 -0
- karrio/providers/australiapost/error.py +41 -0
- karrio/providers/australiapost/manifest.py +62 -0
- karrio/providers/australiapost/rate.py +141 -0
- karrio/providers/australiapost/shipment/__init__.py +9 -0
- karrio/providers/australiapost/shipment/cancel.py +38 -0
- karrio/providers/australiapost/shipment/create.py +294 -0
- karrio/providers/australiapost/tracking.py +84 -0
- karrio/providers/australiapost/units.py +159 -0
- karrio/providers/australiapost/utils.py +34 -0
- karrio/schemas/australiapost/__init__.py +0 -0
- karrio/schemas/australiapost/error_response.py +22 -0
- karrio/schemas/australiapost/label_request.py +37 -0
- karrio/schemas/australiapost/label_response.py +31 -0
- karrio/schemas/australiapost/manifest_request.py +16 -0
- karrio/schemas/australiapost/manifest_response.py +94 -0
- karrio/schemas/australiapost/rate_request.py +29 -0
- karrio/schemas/australiapost/rate_response.py +76 -0
- karrio/schemas/australiapost/shipment_request.py +162 -0
- karrio/schemas/australiapost/shipment_response.py +59 -0
- karrio/schemas/australiapost/tracking_request.py +8 -0
- karrio/schemas/australiapost/tracking_response.py +55 -0
- karrio_australiapost-2025.5.dist-info/METADATA +45 -0
- karrio_australiapost-2025.5.dist-info/RECORD +32 -0
- karrio_australiapost-2025.5.dist-info/WHEEL +5 -0
- karrio_australiapost-2025.5.dist-info/entry_points.txt +2 -0
- karrio_australiapost-2025.5.dist-info/top_level.txt +3 -0
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import karrio.schemas.australiapost.shipment_request as australiapost
|
|
2
|
+
import karrio.schemas.australiapost.shipment_response as shipping
|
|
3
|
+
import karrio.schemas.australiapost.label_request as label_request
|
|
4
|
+
import karrio.schemas.australiapost.label_response as labels
|
|
5
|
+
import typing
|
|
6
|
+
import karrio.lib as lib
|
|
7
|
+
import karrio.core.units as units
|
|
8
|
+
import karrio.core.models as models
|
|
9
|
+
import karrio.providers.australiapost.error as error
|
|
10
|
+
import karrio.providers.australiapost.utils as provider_utils
|
|
11
|
+
import karrio.providers.australiapost.units as provider_units
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def parse_shipment_response(
|
|
15
|
+
_response: lib.Deserializable[
|
|
16
|
+
typing.Tuple[dict, typing.Optional[dict], typing.Optional[str]]
|
|
17
|
+
],
|
|
18
|
+
settings: provider_utils.Settings,
|
|
19
|
+
) -> typing.Tuple[typing.List[models.RateDetails], typing.List[models.Message]]:
|
|
20
|
+
[shipment_response, label_response, label] = _response.deserialize()
|
|
21
|
+
shipments = shipment_response.get("shipments") or []
|
|
22
|
+
labels = label_response.get("labels") or []
|
|
23
|
+
messages = [
|
|
24
|
+
*error.parse_error_response(label_response, settings),
|
|
25
|
+
*error.parse_error_response(shipment_response, settings),
|
|
26
|
+
]
|
|
27
|
+
shipment = (
|
|
28
|
+
_extract_details((shipments[0], labels[0], label), settings)
|
|
29
|
+
if label is not None
|
|
30
|
+
else None
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
return shipment, messages
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def _extract_details(
|
|
37
|
+
data: typing.Tuple[dict, dict, str],
|
|
38
|
+
settings: provider_utils.Settings,
|
|
39
|
+
ctx: dict = {},
|
|
40
|
+
) -> models.ShipmentDetails:
|
|
41
|
+
[shipment_response, label_response, label] = data
|
|
42
|
+
label_format = ctx.get("label_format") or "PDF"
|
|
43
|
+
label_info = lib.to_object(labels.LabelType, label_response)
|
|
44
|
+
shipment = lib.to_object(shipping.ShipmentType, shipment_response)
|
|
45
|
+
article_ids = [item.tracking_details.article_id for item in shipment.items]
|
|
46
|
+
tracking_numbers = [item.tracking_details.consignment_id for item in shipment.items]
|
|
47
|
+
|
|
48
|
+
return models.ShipmentDetails(
|
|
49
|
+
carrier_id=settings.carrier_id,
|
|
50
|
+
carrier_name=settings.carrier_name,
|
|
51
|
+
tracking_number=tracking_numbers[0],
|
|
52
|
+
shipment_identifier=shipment.shipment_id,
|
|
53
|
+
label_type=label_format,
|
|
54
|
+
docs=models.Documents(label=label),
|
|
55
|
+
meta=dict(
|
|
56
|
+
carrier_tracking_link=settings.tracking_url.format(tracking_numbers[0]),
|
|
57
|
+
label_request_id=label_info.request_id,
|
|
58
|
+
tracking_numbers=tracking_numbers,
|
|
59
|
+
article_ids=article_ids,
|
|
60
|
+
manifest_required=True,
|
|
61
|
+
),
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def shipment_request(
|
|
66
|
+
payload: models.ShipmentRequest,
|
|
67
|
+
settings: provider_utils.Settings,
|
|
68
|
+
) -> lib.Serializable:
|
|
69
|
+
shipper = lib.to_address(payload.shipper)
|
|
70
|
+
recipient = lib.to_address(payload.recipient)
|
|
71
|
+
service = provider_units.ShippingService.map(payload.service)
|
|
72
|
+
is_intl = shipper.country_code != recipient.country_code
|
|
73
|
+
options = lib.to_shipping_options(
|
|
74
|
+
payload.options,
|
|
75
|
+
initializer=provider_units.shipping_options_initializer,
|
|
76
|
+
)
|
|
77
|
+
packages = lib.to_packages(
|
|
78
|
+
payload.parcels,
|
|
79
|
+
options=options,
|
|
80
|
+
package_option_type=provider_units.ShippingOption,
|
|
81
|
+
shipping_options_initializer=provider_units.shipping_options_initializer,
|
|
82
|
+
)
|
|
83
|
+
customs = lib.to_customs_info(payload.customs, weight_unit=units.WeightUnit.KG.name)
|
|
84
|
+
label_format, label_layout = provider_units.LabelType.map(
|
|
85
|
+
payload.label_type or "PDF"
|
|
86
|
+
).value
|
|
87
|
+
label_group = (
|
|
88
|
+
provider_units.ServiceLabelGroup.map(service.name).value
|
|
89
|
+
or provider_units.ServiceLabelGroup.australiapost_parcel_post.value
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
request = dict(
|
|
93
|
+
shipment=australiapost.ShipmentRequestType(
|
|
94
|
+
shipments=[
|
|
95
|
+
australiapost.ShipmentType(
|
|
96
|
+
shipment_reference=payload.reference,
|
|
97
|
+
customer_reference_1=None,
|
|
98
|
+
customer_reference_2=None,
|
|
99
|
+
email_tracking_enabled=options.email_notification.state,
|
|
100
|
+
shipment_from=australiapost.FromType(
|
|
101
|
+
name=shipper.contact,
|
|
102
|
+
lines=shipper.address_lines,
|
|
103
|
+
suburb=shipper.city,
|
|
104
|
+
state=shipper.state_code,
|
|
105
|
+
postcode=shipper.postal_code,
|
|
106
|
+
country=shipper.country_code,
|
|
107
|
+
email=shipper.email,
|
|
108
|
+
phone=shipper.phone_number,
|
|
109
|
+
),
|
|
110
|
+
to=australiapost.FromType(
|
|
111
|
+
name=recipient.contact,
|
|
112
|
+
lines=recipient.address_lines,
|
|
113
|
+
suburb=recipient.city,
|
|
114
|
+
state=recipient.state_code,
|
|
115
|
+
postcode=recipient.postal_code,
|
|
116
|
+
country=recipient.country_code,
|
|
117
|
+
email=recipient.email,
|
|
118
|
+
phone=recipient.phone_number,
|
|
119
|
+
),
|
|
120
|
+
items=[
|
|
121
|
+
australiapost.ItemType(
|
|
122
|
+
item_reference=getattr(package, "id", None) or str(idx),
|
|
123
|
+
product_id=service.value_or_key,
|
|
124
|
+
length=package.length.CM,
|
|
125
|
+
width=package.width.CM,
|
|
126
|
+
height=package.height.CM,
|
|
127
|
+
weight=package.weight.KG,
|
|
128
|
+
cubic_volume=None,
|
|
129
|
+
transportable_by_air=package.options.transportable_by_air.state,
|
|
130
|
+
authority_to_leave=package.options.australiapost_authority_to_leave.state,
|
|
131
|
+
allow_partial_delivery=package.options.australiapost_allow_partial_delivery.state,
|
|
132
|
+
contains_dangerous_goods=package.options.australiapost_contains_dangerous_goods.state,
|
|
133
|
+
item_description=package.parcel.description,
|
|
134
|
+
features=(
|
|
135
|
+
australiapost.FeaturesType(
|
|
136
|
+
DELIVERY_DATE=(
|
|
137
|
+
australiapost.DELIVERYDATEAttributesType(
|
|
138
|
+
date=package.options.australiapost_delivery_date.state,
|
|
139
|
+
)
|
|
140
|
+
if package.options.australiapost_delivery_date.state
|
|
141
|
+
else None
|
|
142
|
+
),
|
|
143
|
+
DELIVERY_TIMES=(
|
|
144
|
+
australiapost.DELIVERYTIMESAttributesType(
|
|
145
|
+
windows=australiapost.WindowType(
|
|
146
|
+
start=package.options.australiapost_delivery_time_start.state,
|
|
147
|
+
end=package.options.australiapost_delivery_time_end.state,
|
|
148
|
+
)
|
|
149
|
+
)
|
|
150
|
+
if any(
|
|
151
|
+
[
|
|
152
|
+
package.options.australiapost_delivery_time_start.state,
|
|
153
|
+
package.options.australiapost_delivery_time_end.state,
|
|
154
|
+
]
|
|
155
|
+
)
|
|
156
|
+
else None
|
|
157
|
+
),
|
|
158
|
+
PICKUP_DATE=(
|
|
159
|
+
australiapost.DateType(
|
|
160
|
+
attributes=australiapost.DELIVERYDATEAttributesType(
|
|
161
|
+
date=package.options.australiapost_pickup_date.state,
|
|
162
|
+
)
|
|
163
|
+
)
|
|
164
|
+
if package.options.australiapost_pickup_date.state
|
|
165
|
+
else None
|
|
166
|
+
),
|
|
167
|
+
PICKUP_TIME=(
|
|
168
|
+
australiapost.PickupTimeType(
|
|
169
|
+
attributes=australiapost.PICKUPTIMEAttributesType(
|
|
170
|
+
time=package.options.australiapost_pickup_time.state,
|
|
171
|
+
)
|
|
172
|
+
)
|
|
173
|
+
if package.options.australiapost_pickup_time.state
|
|
174
|
+
else None
|
|
175
|
+
),
|
|
176
|
+
IDENTITY_ON_DELIVERY=(
|
|
177
|
+
australiapost.IdentityOnDeliveryType(
|
|
178
|
+
attributes=australiapost.IDENTITYONDELIVERYAttributesType(
|
|
179
|
+
id_capture_type=package.options.australiapost_identity_on_delivery.state,
|
|
180
|
+
redirection_enabled=None,
|
|
181
|
+
)
|
|
182
|
+
)
|
|
183
|
+
if package.options.australiapost_identity_on_delivery.state
|
|
184
|
+
else None
|
|
185
|
+
),
|
|
186
|
+
PRINT_AT_DEPOT=(
|
|
187
|
+
australiapost.PrintAtDepotType(
|
|
188
|
+
attributes=australiapost.PRINTATDEPOTAttributesType(
|
|
189
|
+
enabled=package.options.australiapost_print_at_depot.state,
|
|
190
|
+
)
|
|
191
|
+
)
|
|
192
|
+
if package.options.australiapost_print_at_depot.state
|
|
193
|
+
else None
|
|
194
|
+
),
|
|
195
|
+
SAMEDAY_IDENTITY_ON_DELIVERY=(
|
|
196
|
+
australiapost.SamedayIdentityOnDeliveryType(
|
|
197
|
+
attributes=australiapost.SAMEDAYIDENTITYONDELIVERYAttributesType(
|
|
198
|
+
id_option=package.options.australiapost_sameday_identity_on_delivery.state,
|
|
199
|
+
)
|
|
200
|
+
)
|
|
201
|
+
if package.options.australiapost_sameday_identity_on_delivery.state
|
|
202
|
+
else None
|
|
203
|
+
),
|
|
204
|
+
COMMERCIAL_CLEARANCE=(
|
|
205
|
+
australiapost.CommercialClearanceType()
|
|
206
|
+
if payload.customs
|
|
207
|
+
else None
|
|
208
|
+
),
|
|
209
|
+
)
|
|
210
|
+
if any(
|
|
211
|
+
[
|
|
212
|
+
package.options.australiapost_delivery_date.state,
|
|
213
|
+
package.options.australiapost_delivery_time_start.state,
|
|
214
|
+
package.options.australiapost_delivery_time_end.state,
|
|
215
|
+
package.options.australiapost_pickup_date.state,
|
|
216
|
+
package.options.australiapost_pickup_time.state,
|
|
217
|
+
package.options.australiapost_identity_on_delivery.state,
|
|
218
|
+
package.options.australiapost_print_at_depot.state,
|
|
219
|
+
package.options.australiapost_sameday_identity_on_delivery.state,
|
|
220
|
+
payload.customs,
|
|
221
|
+
]
|
|
222
|
+
)
|
|
223
|
+
else None
|
|
224
|
+
),
|
|
225
|
+
classification_type=(
|
|
226
|
+
# fmt: off
|
|
227
|
+
provider_units.ContentType.map(customs.content_type).value or "OTHER"
|
|
228
|
+
if payload.customs
|
|
229
|
+
else None
|
|
230
|
+
# fmt: on
|
|
231
|
+
),
|
|
232
|
+
commercial_value=customs.commercial_invoice,
|
|
233
|
+
description_of_other=customs.content_description,
|
|
234
|
+
export_declaration_number=customs.options.export_declaration_number.state,
|
|
235
|
+
import_reference_number=customs.options.import_reference_number.state,
|
|
236
|
+
item_contents=(
|
|
237
|
+
[
|
|
238
|
+
australiapost.ItemContentType(
|
|
239
|
+
country_of_origin=content.country,
|
|
240
|
+
description=content.description,
|
|
241
|
+
sku=content.sku,
|
|
242
|
+
quantity=content.quantity,
|
|
243
|
+
tariff_code=content.hs_code,
|
|
244
|
+
value=content.value_amount,
|
|
245
|
+
weight=content.weight,
|
|
246
|
+
item_contents_reference=None,
|
|
247
|
+
)
|
|
248
|
+
for content in (
|
|
249
|
+
package.items
|
|
250
|
+
if any(package.items)
|
|
251
|
+
else customs.commodities
|
|
252
|
+
)
|
|
253
|
+
]
|
|
254
|
+
if is_intl
|
|
255
|
+
else []
|
|
256
|
+
),
|
|
257
|
+
)
|
|
258
|
+
for idx, package in enumerate(packages, start=1)
|
|
259
|
+
],
|
|
260
|
+
movement_type="DESPATCH",
|
|
261
|
+
)
|
|
262
|
+
]
|
|
263
|
+
),
|
|
264
|
+
label=label_request.LabelRequestType(
|
|
265
|
+
wait_for_label_url=True,
|
|
266
|
+
preferences=[
|
|
267
|
+
label_request.PreferenceType(
|
|
268
|
+
type="PRINT",
|
|
269
|
+
format=label_format,
|
|
270
|
+
groups=[
|
|
271
|
+
label_request.GroupType(
|
|
272
|
+
group=label_group,
|
|
273
|
+
layout=label_layout,
|
|
274
|
+
branded=True,
|
|
275
|
+
left_offset=0,
|
|
276
|
+
top_offset=0,
|
|
277
|
+
)
|
|
278
|
+
],
|
|
279
|
+
)
|
|
280
|
+
],
|
|
281
|
+
shipments=[label_request.ShipmentType(shipment_id="[SHIPMENT_ID]")],
|
|
282
|
+
),
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
return lib.Serializable(
|
|
286
|
+
request,
|
|
287
|
+
lambda _: dict(
|
|
288
|
+
shipment=lib.to_dict(
|
|
289
|
+
lib.to_json(_["shipment"]).replace("shipment_from", "from")
|
|
290
|
+
),
|
|
291
|
+
label=lib.to_dict(_["label"]),
|
|
292
|
+
),
|
|
293
|
+
dict(label_format=label_format),
|
|
294
|
+
)
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import karrio.schemas.australiapost.tracking_request as australiapost
|
|
2
|
+
import karrio.schemas.australiapost.tracking_response as tracking
|
|
3
|
+
import typing
|
|
4
|
+
import karrio.lib as lib
|
|
5
|
+
import karrio.core.units as units
|
|
6
|
+
import karrio.core.models as models
|
|
7
|
+
import karrio.providers.australiapost.error as error
|
|
8
|
+
import karrio.providers.australiapost.utils as provider_utils
|
|
9
|
+
import karrio.providers.australiapost.units as provider_units
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def parse_tracking_response(
|
|
13
|
+
_response: lib.Deserializable[dict],
|
|
14
|
+
settings: provider_utils.Settings,
|
|
15
|
+
) -> typing.Tuple[typing.List[models.TrackingDetails], typing.List[models.Message]]:
|
|
16
|
+
response = _response.deserialize()
|
|
17
|
+
tracking_results = response.get("tracking_results") or []
|
|
18
|
+
messages = sum(
|
|
19
|
+
[
|
|
20
|
+
error.parse_error_response(
|
|
21
|
+
result,
|
|
22
|
+
settings,
|
|
23
|
+
tracking_number=result.get("tracking_id"),
|
|
24
|
+
)
|
|
25
|
+
for result in tracking_results
|
|
26
|
+
if "errors" in result
|
|
27
|
+
],
|
|
28
|
+
start=error.parse_error_response(response, settings),
|
|
29
|
+
)
|
|
30
|
+
tracking_details = [
|
|
31
|
+
_extract_details(details, settings)
|
|
32
|
+
for details in tracking_results
|
|
33
|
+
if "trackable_items" in details
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
return tracking_details, messages
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _extract_details(
|
|
40
|
+
data: dict,
|
|
41
|
+
settings: provider_utils.Settings,
|
|
42
|
+
) -> models.TrackingDetails:
|
|
43
|
+
detail = lib.to_object(tracking.TrackingResultType, data)
|
|
44
|
+
item = detail.trackable_items[0]
|
|
45
|
+
status = next(
|
|
46
|
+
(
|
|
47
|
+
status.name
|
|
48
|
+
for status in list(provider_units.TrackingStatus)
|
|
49
|
+
if item.status in status.value
|
|
50
|
+
),
|
|
51
|
+
provider_units.TrackingStatus.in_transit.name,
|
|
52
|
+
)
|
|
53
|
+
|
|
54
|
+
return models.TrackingDetails(
|
|
55
|
+
carrier_name=settings.carrier_name,
|
|
56
|
+
carrier_id=settings.carrier_id,
|
|
57
|
+
tracking_number=detail.tracking_id,
|
|
58
|
+
events=[
|
|
59
|
+
models.TrackingEvent(
|
|
60
|
+
date=lib.fdate(event.date, "%Y-%m-%dT%H:%M:%S%z"),
|
|
61
|
+
description=event.description,
|
|
62
|
+
location=event.location,
|
|
63
|
+
time=lib.flocaltime(event.date, "%Y-%m-%dT%H:%M:%S%z"),
|
|
64
|
+
)
|
|
65
|
+
for event in item.events
|
|
66
|
+
],
|
|
67
|
+
delivered=(status == provider_units.TrackingStatus.delivered.name),
|
|
68
|
+
status=status,
|
|
69
|
+
info=models.TrackingInfo(
|
|
70
|
+
carrier_tracking_link=settings.tracking_url.format(detail.tracking_id),
|
|
71
|
+
shipment_service=item.product_type,
|
|
72
|
+
),
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def tracking_request(
|
|
77
|
+
payload: models.TrackingRequest,
|
|
78
|
+
settings: provider_utils.Settings,
|
|
79
|
+
) -> lib.Serializable:
|
|
80
|
+
request = australiapost.TrackingRequestType(
|
|
81
|
+
tracking_ids=payload.tracking_numbers,
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
return lib.Serializable(request, lib.to_dict)
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import karrio.lib as lib
|
|
2
|
+
import karrio.core.units as units
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class PackagingType(lib.StrEnum):
|
|
6
|
+
"""Carrier specific packaging type"""
|
|
7
|
+
|
|
8
|
+
box = "BOX"
|
|
9
|
+
carton = "CTN"
|
|
10
|
+
pallet = "PAL"
|
|
11
|
+
satchel = "SAT"
|
|
12
|
+
bag = "BAG"
|
|
13
|
+
envelope = "ENV"
|
|
14
|
+
item = "ITM"
|
|
15
|
+
jiffy_bag = "JIF"
|
|
16
|
+
skid = "SKI"
|
|
17
|
+
|
|
18
|
+
""" Unified Packaging type mapping """
|
|
19
|
+
pak = satchel
|
|
20
|
+
tube = item
|
|
21
|
+
small_box = box
|
|
22
|
+
medium_box = box
|
|
23
|
+
your_packaging = box
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class LabelType(lib.Enum):
|
|
27
|
+
PDF_A4_1pp = ("PDF", "A4-1pp")
|
|
28
|
+
ZPL_A4_1pp = ("ZPL", "A4-1pp")
|
|
29
|
+
PDF_A4_3pp = ("PDF", "A4-3pp")
|
|
30
|
+
ZPL_A4_3pp = ("ZPL", "A4-3pp")
|
|
31
|
+
PDF_A4_4pp = ("PDF", "A4-4pp")
|
|
32
|
+
ZPL_A4_4pp = ("ZPL", "A4-4pp")
|
|
33
|
+
PDF_A6_1pp = ("PDF", "A6-1pp")
|
|
34
|
+
ZPL_A6_1pp = ("ZPL", "A6-1pp")
|
|
35
|
+
PDF_A4_2pp = ("PDF", "A4-2pp")
|
|
36
|
+
ZPL_A4_2pp = ("ZPL", "A4-2pp")
|
|
37
|
+
PDF_A4_1pp_landscape = ("PDF", "A4-1pp landscape")
|
|
38
|
+
ZPL_A4_1pp_landscape = ("ZPL", "A4-1pp landscape")
|
|
39
|
+
PDF_A4_2pp_landscape = ("PDF", "A4-2pp landscape")
|
|
40
|
+
ZPL_A4_2pp_landscape = ("ZPL", "A4-2pp landscape")
|
|
41
|
+
|
|
42
|
+
""" Unified Label type mapping """
|
|
43
|
+
PDF = PDF_A4_1pp
|
|
44
|
+
ZPL = PDF_A4_1pp
|
|
45
|
+
PNG = PDF_A4_1pp
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class CustomsContentType(lib.StrEnum):
|
|
49
|
+
"""Carrier specific customs content type"""
|
|
50
|
+
|
|
51
|
+
document = "DOCUMENT"
|
|
52
|
+
gift = "GIFT"
|
|
53
|
+
sample = "SAMPLE"
|
|
54
|
+
other = "OTHER"
|
|
55
|
+
return_of_goods = "RETURN"
|
|
56
|
+
sale_of_goods = "SALE_OF_GOODS"
|
|
57
|
+
|
|
58
|
+
""" Unified Content type mapping """
|
|
59
|
+
documents = document
|
|
60
|
+
merchandise = sale_of_goods
|
|
61
|
+
return_merchandise = return_of_goods
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class ServiceLabelGroup(lib.StrEnum):
|
|
65
|
+
"""Carrier specific services"""
|
|
66
|
+
|
|
67
|
+
australiapost_parcel_post = "Parcel Post"
|
|
68
|
+
australiapost_express_post = "Express Post"
|
|
69
|
+
australiapost_startrack_courier = "Startrack Courier"
|
|
70
|
+
australiapost_startrack = "StarTrack"
|
|
71
|
+
australiapost_on_demand = "On Demand"
|
|
72
|
+
australiapost_international = "International"
|
|
73
|
+
australiapost_commercial = "Commercial"
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class ShippingService(lib.StrEnum):
|
|
77
|
+
"""Carrier specific services"""
|
|
78
|
+
|
|
79
|
+
australiapost_parcel_post = "T28"
|
|
80
|
+
australiapost_express_post = "E34"
|
|
81
|
+
australiapost_parcel_post_signature = "3D55"
|
|
82
|
+
australiapost_express_post_signature = "3J55"
|
|
83
|
+
australiapost_intl_standard_pack_track = "PTI8"
|
|
84
|
+
australiapost_intl_standard_with_signature = "PTI7"
|
|
85
|
+
australiapost_intl_express_merch = "ECM8"
|
|
86
|
+
australiapost_intl_express_docs = "ECD8"
|
|
87
|
+
australiapost_eparcel_post_returns = "PR"
|
|
88
|
+
australiapost_express_eparcel_post_returns = "XPR"
|
|
89
|
+
|
|
90
|
+
# australiapost_parcel_post = "PARCEL POST"
|
|
91
|
+
# australiapost_express_post = "EXPRESS POST"
|
|
92
|
+
# australiapost_parcel_post_signature = "PARCEL POST + SIGNATURE"
|
|
93
|
+
# australiapost_express_post_signature = "EXPRESS POST + SIGNATURE"
|
|
94
|
+
# australiapost_intl_standard_pack_track = "INTL STANDARD/PACK & TRACK"
|
|
95
|
+
# australiapost_intl_standard_with_signature = "INT'L STANDARD WITH SIGNATURE"
|
|
96
|
+
# australiapost_intl_express_merch = "INTL EXPRESS MERCH"
|
|
97
|
+
# australiapost_intl_express_docs = "INTL EXPRESS DOCS"
|
|
98
|
+
# australiapost_eparcel_post_returns = "EPARCEL POST RETURNS"
|
|
99
|
+
# australiapost_express_eparcel_post_returns = "EXPRESS EPARCEL POST RETURNS"
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
class ShippingOption(lib.Enum):
|
|
103
|
+
"""Carrier specific options"""
|
|
104
|
+
|
|
105
|
+
# fmt: off
|
|
106
|
+
australiapost_delivery_date = lib.OptionEnum("DELIVERY_DATE")
|
|
107
|
+
australiapost_delivery_time_start = lib.OptionEnum("DELIVERY_TIMES")
|
|
108
|
+
australiapost_delivery_time_end = lib.OptionEnum("DELIVERY_TIMES")
|
|
109
|
+
australiapost_pickup_date = lib.OptionEnum("PICKUP_DATE")
|
|
110
|
+
australiapost_pickup_time = lib.OptionEnum("PICKUP_TIME")
|
|
111
|
+
australiapost_identity_on_delivery = lib.OptionEnum("IDENTITY_ON_DELIVERY")
|
|
112
|
+
australiapost_print_at_depot = lib.OptionEnum("PRINT_AT_DEPOT", bool)
|
|
113
|
+
australiapost_transit_cover = lib.OptionEnum("TRANSIT_COVER", float)
|
|
114
|
+
australiapost_sameday_identity_on_delivery = lib.OptionEnum("SAMEDAY_IDENTITY_ON_DELIVERY")
|
|
115
|
+
|
|
116
|
+
australiapost_authority_to_leave = lib.OptionEnum("authority_to_leave", bool)
|
|
117
|
+
australiapost_allow_partial_delivery = lib.OptionEnum("allow_partial_delivery", bool)
|
|
118
|
+
australiapost_contains_dangerous_goods = lib.OptionEnum("contains_dangerous_goods", bool)
|
|
119
|
+
|
|
120
|
+
""" Unified Option type mapping """
|
|
121
|
+
|
|
122
|
+
insurance = australiapost_transit_cover
|
|
123
|
+
# fmt: on
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def shipping_options_initializer(
|
|
127
|
+
options: dict,
|
|
128
|
+
package_options: units.ShippingOptions = None,
|
|
129
|
+
) -> units.ShippingOptions:
|
|
130
|
+
"""
|
|
131
|
+
Apply default values to the given options.
|
|
132
|
+
"""
|
|
133
|
+
|
|
134
|
+
if package_options is not None:
|
|
135
|
+
options.update(package_options.content)
|
|
136
|
+
|
|
137
|
+
def items_filter(key: str) -> bool:
|
|
138
|
+
return key in ShippingOption and key not in [ # type: ignore
|
|
139
|
+
"australiapost_authority_to_leave",
|
|
140
|
+
"australiapost_allow_partial_delivery",
|
|
141
|
+
"australiapost_contains_dangerous_goods",
|
|
142
|
+
]
|
|
143
|
+
|
|
144
|
+
return units.ShippingOptions(options, ShippingOption, items_filter=items_filter)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class TrackingStatus(lib.Enum):
|
|
148
|
+
on_hold = ["Possible delay", "Held by courier"]
|
|
149
|
+
delivered = ["Delivered", "Delivered in Full"]
|
|
150
|
+
in_transit = ["In transit"]
|
|
151
|
+
delivery_failed = [
|
|
152
|
+
"Article damaged",
|
|
153
|
+
"Cancelled",
|
|
154
|
+
"Cannot be delivered",
|
|
155
|
+
"Unsuccessful Delivery",
|
|
156
|
+
]
|
|
157
|
+
delivery_delayed = ["Possible delay", "To be Re-Delivered"]
|
|
158
|
+
out_for_delivery = ["On Board for Delivery"]
|
|
159
|
+
ready_for_pickup = ["Awaiting collection", "Ready for Pickup"]
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import karrio.core as core
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class Settings(core.Settings):
|
|
6
|
+
"""Australia Post connection settings."""
|
|
7
|
+
|
|
8
|
+
# Carrier specific properties
|
|
9
|
+
api_key: str
|
|
10
|
+
password: str
|
|
11
|
+
account_number: str
|
|
12
|
+
|
|
13
|
+
account_country_code: str = "AU"
|
|
14
|
+
|
|
15
|
+
@property
|
|
16
|
+
def carrier_name(self):
|
|
17
|
+
return "australiapost"
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
def server_url(self):
|
|
21
|
+
return (
|
|
22
|
+
"https://digitalapi.auspost.com.au/test"
|
|
23
|
+
if self.test_mode
|
|
24
|
+
else "https://digitalapi.auspost.com.au"
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
@property
|
|
28
|
+
def tracking_url(self):
|
|
29
|
+
return "https://auspost.com.au/mypost/beta/track/details/{}"
|
|
30
|
+
|
|
31
|
+
@property
|
|
32
|
+
def authorization(self):
|
|
33
|
+
pair = "%s:%s" % (self.api_key, self.password)
|
|
34
|
+
return base64.b64encode(pair.encode("utf-8")).decode("ascii")
|
|
File without changes
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import attr
|
|
2
|
+
import jstruct
|
|
3
|
+
import typing
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@attr.s(auto_attribs=True)
|
|
7
|
+
class ErrorType:
|
|
8
|
+
error_code: typing.Optional[str] = None
|
|
9
|
+
error_name: typing.Optional[str] = None
|
|
10
|
+
code: typing.Optional[str] = None
|
|
11
|
+
name: typing.Optional[str] = None
|
|
12
|
+
message: typing.Optional[str] = None
|
|
13
|
+
field: typing.Optional[str] = None
|
|
14
|
+
context: typing.Optional[typing.List[typing.Any]] = None
|
|
15
|
+
messages: typing.Optional[typing.List[typing.Any]] = None
|
|
16
|
+
error: typing.Optional[str] = None
|
|
17
|
+
error_description: typing.Optional[str] = None
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@attr.s(auto_attribs=True)
|
|
21
|
+
class ErrorResponseType:
|
|
22
|
+
errors: typing.Optional[typing.List[ErrorType]] = jstruct.JList[ErrorType]
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import attr
|
|
2
|
+
import jstruct
|
|
3
|
+
import typing
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@attr.s(auto_attribs=True)
|
|
7
|
+
class GroupType:
|
|
8
|
+
group: typing.Optional[str] = None
|
|
9
|
+
layout: typing.Optional[str] = None
|
|
10
|
+
branded: typing.Optional[bool] = None
|
|
11
|
+
left_offset: typing.Optional[int] = None
|
|
12
|
+
top_offset: typing.Optional[int] = None
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@attr.s(auto_attribs=True)
|
|
16
|
+
class PreferenceType:
|
|
17
|
+
type: typing.Optional[str] = None
|
|
18
|
+
format: typing.Optional[str] = None
|
|
19
|
+
groups: typing.Optional[typing.List[GroupType]] = jstruct.JList[GroupType]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@attr.s(auto_attribs=True)
|
|
23
|
+
class ItemType:
|
|
24
|
+
item_id: typing.Optional[str] = None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@attr.s(auto_attribs=True)
|
|
28
|
+
class ShipmentType:
|
|
29
|
+
shipment_id: typing.Optional[str] = None
|
|
30
|
+
items: typing.Optional[typing.List[ItemType]] = jstruct.JList[ItemType]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@attr.s(auto_attribs=True)
|
|
34
|
+
class LabelRequestType:
|
|
35
|
+
wait_for_label_url: typing.Optional[bool] = None
|
|
36
|
+
preferences: typing.Optional[typing.List[PreferenceType]] = jstruct.JList[PreferenceType]
|
|
37
|
+
shipments: typing.Optional[typing.List[ShipmentType]] = jstruct.JList[ShipmentType]
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import attr
|
|
2
|
+
import jstruct
|
|
3
|
+
import typing
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@attr.s(auto_attribs=True)
|
|
7
|
+
class ItemType:
|
|
8
|
+
item_id: typing.Optional[str] = None
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@attr.s(auto_attribs=True)
|
|
12
|
+
class ShipmentType:
|
|
13
|
+
shipment_id: typing.Optional[str] = None
|
|
14
|
+
options: typing.Optional[typing.List[typing.Any]] = None
|
|
15
|
+
items: typing.Optional[typing.List[ItemType]] = jstruct.JList[ItemType]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@attr.s(auto_attribs=True)
|
|
19
|
+
class LabelType:
|
|
20
|
+
request_id: typing.Optional[str] = None
|
|
21
|
+
url: typing.Optional[str] = None
|
|
22
|
+
status: typing.Optional[str] = None
|
|
23
|
+
request_date: typing.Optional[str] = None
|
|
24
|
+
url_creation_date: typing.Optional[str] = None
|
|
25
|
+
shipments: typing.Optional[typing.List[ShipmentType]] = jstruct.JList[ShipmentType]
|
|
26
|
+
shipment_ids: typing.Optional[typing.List[str]] = None
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
@attr.s(auto_attribs=True)
|
|
30
|
+
class LabelResponseType:
|
|
31
|
+
labels: typing.Optional[typing.List[LabelType]] = jstruct.JList[LabelType]
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import attr
|
|
2
|
+
import jstruct
|
|
3
|
+
import typing
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@attr.s(auto_attribs=True)
|
|
7
|
+
class ShipmentType:
|
|
8
|
+
shipment_id: typing.Optional[str] = None
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@attr.s(auto_attribs=True)
|
|
12
|
+
class ManifestRequestType:
|
|
13
|
+
order_reference: typing.Optional[str] = None
|
|
14
|
+
payment_method: typing.Optional[str] = None
|
|
15
|
+
consignor: typing.Optional[str] = None
|
|
16
|
+
shipments: typing.Optional[typing.List[ShipmentType]] = jstruct.JList[ShipmentType]
|