karrio-australiapost 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/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.5rc1.dist-info/METADATA +45 -0
- karrio_australiapost-2025.5rc1.dist-info/RECORD +32 -0
- karrio_australiapost-2025.5rc1.dist-info/WHEEL +5 -0
- karrio_australiapost-2025.5rc1.dist-info/entry_points.txt +2 -0
- karrio_australiapost-2025.5rc1.dist-info/top_level.txt +3 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"""Karrio Australia Post client mapper."""
|
|
2
|
+
|
|
3
|
+
import typing
|
|
4
|
+
import karrio.lib as lib
|
|
5
|
+
import karrio.api.mapper as mapper
|
|
6
|
+
import karrio.core.models as models
|
|
7
|
+
import karrio.providers.australiapost as provider
|
|
8
|
+
import karrio.mappers.australiapost.settings as provider_settings
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Mapper(mapper.Mapper):
|
|
12
|
+
settings: provider_settings.Settings
|
|
13
|
+
|
|
14
|
+
def create_rate_request(self, payload: models.RateRequest) -> lib.Serializable:
|
|
15
|
+
return provider.rate_request(payload, self.settings)
|
|
16
|
+
|
|
17
|
+
def create_tracking_request(
|
|
18
|
+
self, payload: models.TrackingRequest
|
|
19
|
+
) -> lib.Serializable:
|
|
20
|
+
return provider.tracking_request(payload, self.settings)
|
|
21
|
+
|
|
22
|
+
def create_shipment_request(
|
|
23
|
+
self, payload: models.ShipmentRequest
|
|
24
|
+
) -> lib.Serializable:
|
|
25
|
+
return provider.shipment_request(payload, self.settings)
|
|
26
|
+
|
|
27
|
+
def create_cancel_shipment_request(
|
|
28
|
+
self, payload: models.ShipmentCancelRequest
|
|
29
|
+
) -> lib.Serializable[str]:
|
|
30
|
+
return provider.shipment_cancel_request(payload, self.settings)
|
|
31
|
+
|
|
32
|
+
def create_manifest_request(
|
|
33
|
+
self, payload: models.ManifestRequest
|
|
34
|
+
) -> lib.Serializable:
|
|
35
|
+
return provider.manifest_request(payload, self.settings)
|
|
36
|
+
|
|
37
|
+
def parse_cancel_shipment_response(
|
|
38
|
+
self, response: lib.Deserializable[str]
|
|
39
|
+
) -> typing.Tuple[models.ConfirmationDetails, typing.List[models.Message]]:
|
|
40
|
+
return provider.parse_shipment_cancel_response(response, self.settings)
|
|
41
|
+
|
|
42
|
+
def parse_rate_response(
|
|
43
|
+
self, response: lib.Deserializable[str]
|
|
44
|
+
) -> typing.Tuple[typing.List[models.RateDetails], typing.List[models.Message]]:
|
|
45
|
+
return provider.parse_rate_response(response, self.settings)
|
|
46
|
+
|
|
47
|
+
def parse_shipment_response(
|
|
48
|
+
self, response: lib.Deserializable[str]
|
|
49
|
+
) -> typing.Tuple[models.ShipmentDetails, typing.List[models.Message]]:
|
|
50
|
+
return provider.parse_shipment_response(response, self.settings)
|
|
51
|
+
|
|
52
|
+
def parse_tracking_response(
|
|
53
|
+
self, response: lib.Deserializable[str]
|
|
54
|
+
) -> typing.Tuple[typing.List[models.TrackingDetails], typing.List[models.Message]]:
|
|
55
|
+
return provider.parse_tracking_response(response, self.settings)
|
|
56
|
+
|
|
57
|
+
def parse_manifest_response(
|
|
58
|
+
self, response: lib.Deserializable[str]
|
|
59
|
+
) -> typing.Tuple[models.ManifestDetails, typing.List[models.Message]]:
|
|
60
|
+
return provider.parse_manifest_response(response, self.settings)
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
"""Karrio Australia Post client proxy."""
|
|
2
|
+
|
|
3
|
+
import karrio.lib as lib
|
|
4
|
+
import karrio.api.proxy as proxy
|
|
5
|
+
import karrio.mappers.australiapost.settings as provider_settings
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Proxy(proxy.Proxy):
|
|
9
|
+
settings: provider_settings.Settings
|
|
10
|
+
|
|
11
|
+
def get_rates(self, request: lib.Serializable) -> lib.Deserializable[str]:
|
|
12
|
+
response = lib.request(
|
|
13
|
+
url=f"{self.settings.server_url}/shipping/v1/prices/items",
|
|
14
|
+
data=lib.to_json(request.serialize()),
|
|
15
|
+
trace=self.trace_as("json"),
|
|
16
|
+
method="POST",
|
|
17
|
+
headers={
|
|
18
|
+
"Accept": "application/json",
|
|
19
|
+
"Content-Type": "application/json",
|
|
20
|
+
"Account-Number": self.settings.account_number,
|
|
21
|
+
"Authorization": f"Basic {self.settings.authorization}",
|
|
22
|
+
},
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
return lib.Deserializable(response, lib.to_dict)
|
|
26
|
+
|
|
27
|
+
def create_shipment(self, request: lib.Serializable) -> lib.Deserializable[str]:
|
|
28
|
+
payload = request.serialize()
|
|
29
|
+
responses: list = []
|
|
30
|
+
responses.append(
|
|
31
|
+
lib.request(
|
|
32
|
+
url=f"{self.settings.server_url}/shipping/v1/shipments",
|
|
33
|
+
data=lib.to_json(payload["shipment"]),
|
|
34
|
+
trace=self.trace_as("json"),
|
|
35
|
+
method="POST",
|
|
36
|
+
headers={
|
|
37
|
+
"Accept": "application/json",
|
|
38
|
+
"Content-Type": "application/json",
|
|
39
|
+
"Account-Number": self.settings.account_number,
|
|
40
|
+
"Authorization": f"Basic {self.settings.authorization}",
|
|
41
|
+
},
|
|
42
|
+
)
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
shipment_id = (lib.to_dict(responses[0]).get("shipments") or [{}])[0].get(
|
|
46
|
+
"shipment_id"
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
if shipment_id is not None:
|
|
50
|
+
responses.append(
|
|
51
|
+
lib.request(
|
|
52
|
+
url=f"{self.settings.server_url}/shipping/v1/labels",
|
|
53
|
+
trace=self.trace_as("json"),
|
|
54
|
+
data=lib.to_json(payload["label"]).replace(
|
|
55
|
+
"[SHIPMENT_ID]", shipment_id
|
|
56
|
+
),
|
|
57
|
+
method="POST",
|
|
58
|
+
headers={
|
|
59
|
+
"Accept": "application/json",
|
|
60
|
+
"Content-Type": "application/json",
|
|
61
|
+
"Account-Number": self.settings.account_number,
|
|
62
|
+
"Authorization": f"Basic {self.settings.authorization}",
|
|
63
|
+
},
|
|
64
|
+
)
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
label_url = (lib.to_dict(responses[1]).get("labels") or [{}])[0].get("url")
|
|
68
|
+
|
|
69
|
+
if label_url is not None:
|
|
70
|
+
responses.append(
|
|
71
|
+
lib.request(
|
|
72
|
+
decoder=lib.encode_base64,
|
|
73
|
+
url=label_url,
|
|
74
|
+
method="GET",
|
|
75
|
+
)
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
return lib.Deserializable(
|
|
79
|
+
responses,
|
|
80
|
+
lambda _: [
|
|
81
|
+
# parse create shipment response
|
|
82
|
+
lib.to_dict(_[0]),
|
|
83
|
+
# parse create label response if exists
|
|
84
|
+
lib.to_dict(_[1] if len(_) > 1 else "{}"),
|
|
85
|
+
# return label image if exists
|
|
86
|
+
(_[2] if len(_) > 2 else None),
|
|
87
|
+
],
|
|
88
|
+
request.ctx,
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
def cancel_shipment(self, request: lib.Serializable) -> lib.Deserializable[str]:
|
|
92
|
+
payload = request.serialize()
|
|
93
|
+
response = lib.request(
|
|
94
|
+
url=f"{self.settings.server_url}/shipping/v1/shipments/{payload['shipment_id']}",
|
|
95
|
+
trace=self.trace_as("json"),
|
|
96
|
+
method="DELETE",
|
|
97
|
+
headers={
|
|
98
|
+
"Accept": "application/json",
|
|
99
|
+
"Content-Type": "application/json",
|
|
100
|
+
"Account-Number": self.settings.account_number,
|
|
101
|
+
"Authorization": f"Basic {self.settings.authorization}",
|
|
102
|
+
},
|
|
103
|
+
decoder=lambda _: dict(ok=True),
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
return lib.Deserializable(response, lib.to_dict)
|
|
107
|
+
|
|
108
|
+
def get_tracking(self, request: lib.Serializable) -> lib.Deserializable[str]:
|
|
109
|
+
query = request.serialize()
|
|
110
|
+
tracking_ids = ",".join(query["tracking_ids"])
|
|
111
|
+
response = lib.request(
|
|
112
|
+
url=f"{self.settings.server_url}/shipping/v1/track?tracking_ids={tracking_ids}",
|
|
113
|
+
trace=self.trace_as("json"),
|
|
114
|
+
method="GET",
|
|
115
|
+
headers={
|
|
116
|
+
"Accept": "application/json",
|
|
117
|
+
"Content-Type": "application/json",
|
|
118
|
+
"Account-Number": self.settings.account_number,
|
|
119
|
+
"Authorization": f"Basic {self.settings.authorization}",
|
|
120
|
+
},
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
return lib.Deserializable(response, lib.to_dict)
|
|
124
|
+
|
|
125
|
+
def create_manifest(self, request: lib.Serializable) -> lib.Deserializable:
|
|
126
|
+
ctx: dict = {}
|
|
127
|
+
response = lib.request(
|
|
128
|
+
url=f"{self.settings.server_url}/shipping/v1/orders",
|
|
129
|
+
data=lib.to_json(request.serialize()),
|
|
130
|
+
trace=self.trace_as("json"),
|
|
131
|
+
method="POST",
|
|
132
|
+
headers={
|
|
133
|
+
"Accept": "application/json",
|
|
134
|
+
"Content-Type": "application/json",
|
|
135
|
+
"Account-Number": self.settings.account_number,
|
|
136
|
+
"Authorization": f"Basic {self.settings.authorization}",
|
|
137
|
+
},
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
order_id = lib.to_dict(response).get("order", {}).get("order_id")
|
|
141
|
+
|
|
142
|
+
if order_id is not None:
|
|
143
|
+
ctx.update(
|
|
144
|
+
manifest=lib.request(
|
|
145
|
+
url=f"{self.settings.server_url}/shipping/v1/accounts/{self.settings.account_number}/orders/{order_id}/summary",
|
|
146
|
+
decoder=lib.encode_base64,
|
|
147
|
+
method="GET",
|
|
148
|
+
)
|
|
149
|
+
)
|
|
150
|
+
|
|
151
|
+
return lib.Deserializable(response, lib.to_dict, ctx=ctx)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Karrio Australia Post client settings."""
|
|
2
|
+
|
|
3
|
+
import attr
|
|
4
|
+
import karrio.providers.australiapost.utils as provider_utils
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@attr.s(auto_attribs=True)
|
|
8
|
+
class Settings(provider_utils.Settings):
|
|
9
|
+
"""Australia Post connection settings."""
|
|
10
|
+
|
|
11
|
+
# required carrier specific properties
|
|
12
|
+
api_key: str
|
|
13
|
+
password: str
|
|
14
|
+
account_number: str
|
|
15
|
+
|
|
16
|
+
# generic properties
|
|
17
|
+
id: str = None
|
|
18
|
+
test_mode: bool = False
|
|
19
|
+
carrier_id: str = "australiapost"
|
|
20
|
+
account_country_code: str = "AU"
|
|
21
|
+
metadata: dict = {}
|
|
22
|
+
config: dict = {}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import karrio.core.metadata as metadata
|
|
2
|
+
import karrio.mappers.australiapost as mappers
|
|
3
|
+
import karrio.providers.australiapost.units as units
|
|
4
|
+
import karrio.providers.australiapost.utils as utils
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
METADATA = metadata.PluginMetadata(
|
|
8
|
+
status="beta",
|
|
9
|
+
id="australiapost",
|
|
10
|
+
label="Australia Post",
|
|
11
|
+
# Integrations
|
|
12
|
+
Mapper=mappers.Mapper,
|
|
13
|
+
Proxy=mappers.Proxy,
|
|
14
|
+
Settings=mappers.Settings,
|
|
15
|
+
# Data Units
|
|
16
|
+
is_hub=False,
|
|
17
|
+
services=units.ShippingService,
|
|
18
|
+
options=units.ShippingOption,
|
|
19
|
+
# New fields
|
|
20
|
+
website="https://auspost.com.au/",
|
|
21
|
+
documentation="https://developers.auspost.com.au/apis/shipping-and-tracking/reference",
|
|
22
|
+
description="Australia Post, formally known as the Australian Postal Corporation, is a Commonwealth government-owned corporation that provides postal services throughout Australia.",
|
|
23
|
+
)
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from karrio.providers.australiapost.utils import Settings
|
|
2
|
+
from karrio.providers.australiapost.rate import parse_rate_response, rate_request
|
|
3
|
+
from karrio.providers.australiapost.shipment import (
|
|
4
|
+
parse_shipment_cancel_response,
|
|
5
|
+
parse_shipment_response,
|
|
6
|
+
shipment_cancel_request,
|
|
7
|
+
shipment_request,
|
|
8
|
+
)
|
|
9
|
+
from karrio.providers.australiapost.tracking import (
|
|
10
|
+
parse_tracking_response,
|
|
11
|
+
tracking_request,
|
|
12
|
+
)
|
|
13
|
+
from karrio.providers.australiapost.manifest import (
|
|
14
|
+
parse_manifest_response,
|
|
15
|
+
manifest_request,
|
|
16
|
+
)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import karrio.schemas.australiapost.error_response as australiapost
|
|
2
|
+
import typing
|
|
3
|
+
import karrio.lib as lib
|
|
4
|
+
import karrio.core.models as models
|
|
5
|
+
import karrio.providers.australiapost.utils as provider_utils
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def parse_error_response(
|
|
9
|
+
response: dict,
|
|
10
|
+
settings: provider_utils.Settings,
|
|
11
|
+
**kwargs,
|
|
12
|
+
) -> typing.List[models.Message]:
|
|
13
|
+
responses = response if isinstance(response, list) else [response]
|
|
14
|
+
error_list: typing.List[dict] = sum(
|
|
15
|
+
[
|
|
16
|
+
*[res.get("errors", []) for res in responses if "errors" in res],
|
|
17
|
+
*[res.get("warnings", []) for res in responses if "warnings" in res],
|
|
18
|
+
],
|
|
19
|
+
[],
|
|
20
|
+
)
|
|
21
|
+
errors: typing.List[australiapost.ErrorType] = [
|
|
22
|
+
lib.to_object(australiapost.ErrorType, error) for error in error_list
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
return [
|
|
26
|
+
models.Message(
|
|
27
|
+
carrier_id=settings.carrier_id,
|
|
28
|
+
carrier_name=settings.carrier_name,
|
|
29
|
+
code=(error.code or error.error_code or error.error),
|
|
30
|
+
message=(error.message or error.error_description or error.name),
|
|
31
|
+
details=lib.to_dict(
|
|
32
|
+
{
|
|
33
|
+
**kwargs,
|
|
34
|
+
"field": error.field,
|
|
35
|
+
"context": error.context,
|
|
36
|
+
"messages": error.messages,
|
|
37
|
+
}
|
|
38
|
+
),
|
|
39
|
+
)
|
|
40
|
+
for error in errors
|
|
41
|
+
]
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import karrio.schemas.australiapost.manifest_request as australiapost
|
|
2
|
+
import karrio.schemas.australiapost.manifest_response as manifest
|
|
3
|
+
import typing
|
|
4
|
+
import karrio.lib as lib
|
|
5
|
+
import karrio.core.models as models
|
|
6
|
+
import karrio.providers.australiapost.error as error
|
|
7
|
+
import karrio.providers.australiapost.utils as provider_utils
|
|
8
|
+
import karrio.providers.australiapost.units as provider_units
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def parse_manifest_response(
|
|
12
|
+
_response: lib.Deserializable[dict],
|
|
13
|
+
settings: provider_utils.Settings,
|
|
14
|
+
) -> typing.Tuple[models.ManifestDetails, typing.List[models.Message]]:
|
|
15
|
+
response = _response.deserialize()
|
|
16
|
+
|
|
17
|
+
messages = error.parse_error_response(response, settings)
|
|
18
|
+
details = (
|
|
19
|
+
_extract_details(response, settings, ctx=_response.ctx)
|
|
20
|
+
if response.get("order", {}).get("order_id") is not None
|
|
21
|
+
else None
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
return details, messages
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def _extract_details(
|
|
28
|
+
data: dict,
|
|
29
|
+
settings: provider_utils.Settings,
|
|
30
|
+
ctx: dict = {},
|
|
31
|
+
) -> models.ManifestDetails:
|
|
32
|
+
manifest = ctx.get("manifest")
|
|
33
|
+
|
|
34
|
+
return models.ManifestDetails(
|
|
35
|
+
carrier_id=settings.carrier_id,
|
|
36
|
+
carrier_name=settings.carrier_id,
|
|
37
|
+
doc=models.ManifestDocument(manifest=manifest),
|
|
38
|
+
meta=dict(
|
|
39
|
+
order_id=data["order"]["order_id"],
|
|
40
|
+
order_reference=data["order"]["order_reference"],
|
|
41
|
+
order_creation_date=data["order"]["order_creation_date"],
|
|
42
|
+
),
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def manifest_request(
|
|
47
|
+
payload: models.ManifestRequest,
|
|
48
|
+
settings: provider_utils.Settings,
|
|
49
|
+
) -> lib.Serializable:
|
|
50
|
+
address = lib.to_address(payload.address)
|
|
51
|
+
|
|
52
|
+
request = australiapost.ManifestRequestType(
|
|
53
|
+
order_reference=lib.text(payload.reference),
|
|
54
|
+
payment_method="CHARGE_TO_ACCOUNT",
|
|
55
|
+
consignor=lib.text(address.company_name or address.contact, max=40),
|
|
56
|
+
shipments=[
|
|
57
|
+
australiapost.ShipmentType(shipment_id=id)
|
|
58
|
+
for id in payload.shipment_identifiers
|
|
59
|
+
],
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
return lib.Serializable(request, lib.to_dict)
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import karrio.schemas.australiapost.rate_request as australiapost
|
|
2
|
+
import karrio.schemas.australiapost.rate_response as rating
|
|
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_rate_response(
|
|
13
|
+
_response: lib.Deserializable[dict],
|
|
14
|
+
settings: provider_utils.Settings,
|
|
15
|
+
) -> typing.Tuple[typing.List[models.RateDetails], typing.List[models.Message]]:
|
|
16
|
+
response = _response.deserialize()
|
|
17
|
+
items = response.get("items") or []
|
|
18
|
+
|
|
19
|
+
messages = sum(
|
|
20
|
+
[
|
|
21
|
+
error.parse_error_response(
|
|
22
|
+
item,
|
|
23
|
+
settings,
|
|
24
|
+
)
|
|
25
|
+
for item in items
|
|
26
|
+
if "errors" in item or "warnings" in item
|
|
27
|
+
],
|
|
28
|
+
start=error.parse_error_response(response, settings),
|
|
29
|
+
)
|
|
30
|
+
rates = lib.to_multi_piece_rates(
|
|
31
|
+
[
|
|
32
|
+
(
|
|
33
|
+
f"{_}",
|
|
34
|
+
[
|
|
35
|
+
_extract_details(price, settings)
|
|
36
|
+
for price in item.get("prices") or []
|
|
37
|
+
],
|
|
38
|
+
)
|
|
39
|
+
for _, item in enumerate(items, start=1)
|
|
40
|
+
]
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
return rates, messages
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def _extract_details(
|
|
47
|
+
data: dict,
|
|
48
|
+
settings: provider_utils.Settings,
|
|
49
|
+
) -> models.RateDetails:
|
|
50
|
+
rate = lib.to_object(rating.PriceElementType, data)
|
|
51
|
+
service = provider_units.ShippingService.map(rate.product_id)
|
|
52
|
+
features = data.get("features") or {}
|
|
53
|
+
charges = [
|
|
54
|
+
("base charge", rate.calculated_price_ex_gst),
|
|
55
|
+
("GST", rate.calculated_gst),
|
|
56
|
+
*[
|
|
57
|
+
(_.type, _.attributes.price.calculated_price)
|
|
58
|
+
for _ in features.values()
|
|
59
|
+
if lib.failsafe(lambda: _.attributes.price.calculated_price) is not None
|
|
60
|
+
],
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
return models.RateDetails(
|
|
64
|
+
carrier_id=settings.carrier_id,
|
|
65
|
+
carrier_name=settings.carrier_name,
|
|
66
|
+
service=service.name_or_key,
|
|
67
|
+
total_charge=lib.to_money(rate.calculated_price),
|
|
68
|
+
currency=units.Currency.AUD.name,
|
|
69
|
+
extra_charges=[
|
|
70
|
+
models.ChargeDetails(
|
|
71
|
+
name=name,
|
|
72
|
+
amount=lib.to_money(value),
|
|
73
|
+
currency=units.Currency.AUD.name,
|
|
74
|
+
)
|
|
75
|
+
for name, value in charges
|
|
76
|
+
if value
|
|
77
|
+
],
|
|
78
|
+
meta=dict(
|
|
79
|
+
service_name=rate.product_type,
|
|
80
|
+
),
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def rate_request(
|
|
85
|
+
payload: models.RateRequest,
|
|
86
|
+
settings: provider_utils.Settings,
|
|
87
|
+
) -> lib.Serializable:
|
|
88
|
+
options = lib.to_shipping_options(
|
|
89
|
+
payload.options,
|
|
90
|
+
initializer=provider_units.shipping_options_initializer,
|
|
91
|
+
)
|
|
92
|
+
packages = lib.to_packages(
|
|
93
|
+
payload.parcels,
|
|
94
|
+
options=options,
|
|
95
|
+
package_option_type=provider_units.ShippingOption,
|
|
96
|
+
shipping_options_initializer=provider_units.shipping_options_initializer,
|
|
97
|
+
)
|
|
98
|
+
services = lib.to_services(payload.services, provider_units.ShippingService)
|
|
99
|
+
|
|
100
|
+
request = australiapost.RateRequestType(
|
|
101
|
+
rate_request_from=australiapost.FromType(
|
|
102
|
+
postcode=payload.shipper.postal_code,
|
|
103
|
+
country=payload.shipper.country_code,
|
|
104
|
+
),
|
|
105
|
+
to=australiapost.FromType(
|
|
106
|
+
postcode=payload.recipient.postal_code,
|
|
107
|
+
country=payload.recipient.country_code,
|
|
108
|
+
),
|
|
109
|
+
items=[
|
|
110
|
+
australiapost.ItemType(
|
|
111
|
+
item_reference=(getattr(package.parcel, "id", None) or str(idx)),
|
|
112
|
+
length=package.length.CM,
|
|
113
|
+
width=package.width.CM,
|
|
114
|
+
height=package.height.CM,
|
|
115
|
+
weight=package.weight.KG,
|
|
116
|
+
packaging_type=provider_units.PackagingType.map(
|
|
117
|
+
package.packaging_type
|
|
118
|
+
).value,
|
|
119
|
+
product_ids=[_.value for _ in services],
|
|
120
|
+
features=lib.identity(
|
|
121
|
+
dict(
|
|
122
|
+
TRANSIT_COVER=dict(
|
|
123
|
+
attributes=dict(
|
|
124
|
+
cover_amount=package.options.australiapost_transit_cover.state,
|
|
125
|
+
),
|
|
126
|
+
)
|
|
127
|
+
)
|
|
128
|
+
if (package.options.australiapost_transit_cover.state is not None)
|
|
129
|
+
else None
|
|
130
|
+
),
|
|
131
|
+
)
|
|
132
|
+
for idx, package in enumerate(packages, start=1)
|
|
133
|
+
],
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
return lib.Serializable(
|
|
137
|
+
request,
|
|
138
|
+
lambda _: lib.to_dict(
|
|
139
|
+
lib.to_json(_).replace("rate_request_from", "from"),
|
|
140
|
+
),
|
|
141
|
+
)
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
import karrio.lib as lib
|
|
3
|
+
import karrio.core.models as models
|
|
4
|
+
import karrio.providers.australiapost.error as error
|
|
5
|
+
import karrio.providers.australiapost.utils as provider_utils
|
|
6
|
+
import karrio.providers.australiapost.units as provider_units
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def parse_shipment_cancel_response(
|
|
10
|
+
_response: lib.Deserializable[dict],
|
|
11
|
+
settings: provider_utils.Settings,
|
|
12
|
+
) -> typing.Tuple[models.ConfirmationDetails, typing.List[models.Message]]:
|
|
13
|
+
response = _response.deserialize()
|
|
14
|
+
|
|
15
|
+
messages = error.parse_error_response(response, settings)
|
|
16
|
+
success = len(messages) == 0
|
|
17
|
+
|
|
18
|
+
confirmation = (
|
|
19
|
+
models.ConfirmationDetails(
|
|
20
|
+
carrier_id=settings.carrier_id,
|
|
21
|
+
carrier_name=settings.carrier_name,
|
|
22
|
+
operation="Cancel Shipment",
|
|
23
|
+
success=success,
|
|
24
|
+
)
|
|
25
|
+
if success
|
|
26
|
+
else None
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
return confirmation, messages
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def shipment_cancel_request(
|
|
33
|
+
payload: models.ShipmentCancelRequest,
|
|
34
|
+
settings: provider_utils.Settings,
|
|
35
|
+
) -> lib.Serializable:
|
|
36
|
+
request = dict(shipment_id=payload.shipment_identifier)
|
|
37
|
+
|
|
38
|
+
return lib.Serializable(request)
|