karrio-sapient 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/sapient/__init__.py +3 -0
- karrio/mappers/sapient/mapper.py +69 -0
- karrio/mappers/sapient/proxy.py +87 -0
- karrio/mappers/sapient/settings.py +36 -0
- karrio/plugins/sapient/__init__.py +20 -0
- karrio/providers/sapient/__init__.py +18 -0
- karrio/providers/sapient/error.py +28 -0
- karrio/providers/sapient/pickup/__init__.py +4 -0
- karrio/providers/sapient/pickup/cancel.py +57 -0
- karrio/providers/sapient/pickup/create.py +87 -0
- karrio/providers/sapient/pickup/update.py +87 -0
- karrio/providers/sapient/shipment/__init__.py +9 -0
- karrio/providers/sapient/shipment/cancel.py +57 -0
- karrio/providers/sapient/shipment/create.py +247 -0
- karrio/providers/sapient/units.py +638 -0
- karrio/providers/sapient/utils.py +122 -0
- karrio/schemas/sapient/__init__.py +0 -0
- karrio/schemas/sapient/error_response.py +16 -0
- karrio/schemas/sapient/pickup_request.py +10 -0
- karrio/schemas/sapient/pickup_response.py +9 -0
- karrio/schemas/sapient/shipment_requests.py +125 -0
- karrio/schemas/sapient/shipment_response.py +24 -0
- karrio_sapient-2025.5rc1.dist-info/METADATA +45 -0
- karrio_sapient-2025.5rc1.dist-info/RECORD +27 -0
- karrio_sapient-2025.5rc1.dist-info/WHEEL +5 -0
- karrio_sapient-2025.5rc1.dist-info/entry_points.txt +2 -0
- karrio_sapient-2025.5rc1.dist-info/top_level.txt +3 -0
@@ -0,0 +1,69 @@
|
|
1
|
+
"""Karrio SAPIENT 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.sapient as provider
|
8
|
+
import karrio.mappers.sapient.settings as provider_settings
|
9
|
+
import karrio.universal.providers.rating as universal_provider
|
10
|
+
|
11
|
+
|
12
|
+
class Mapper(mapper.Mapper):
|
13
|
+
settings: provider_settings.Settings
|
14
|
+
|
15
|
+
def create_rate_request(self, payload: models.RateRequest) -> lib.Serializable:
|
16
|
+
return universal_provider.rate_request(payload, self.settings)
|
17
|
+
|
18
|
+
def create_shipment_request(
|
19
|
+
self, payload: models.ShipmentRequest
|
20
|
+
) -> lib.Serializable:
|
21
|
+
return provider.shipment_request(payload, self.settings)
|
22
|
+
|
23
|
+
def create_pickup_request(self, payload: models.PickupRequest) -> lib.Serializable:
|
24
|
+
return provider.pickup_request(payload, self.settings)
|
25
|
+
|
26
|
+
def create_pickup_update_request(
|
27
|
+
self, payload: models.PickupUpdateRequest
|
28
|
+
) -> lib.Serializable:
|
29
|
+
return provider.pickup_update_request(payload, self.settings)
|
30
|
+
|
31
|
+
def create_cancel_pickup_request(
|
32
|
+
self, payload: models.PickupCancelRequest
|
33
|
+
) -> lib.Serializable:
|
34
|
+
return provider.pickup_cancel_request(payload, self.settings)
|
35
|
+
|
36
|
+
def create_cancel_shipment_request(
|
37
|
+
self, payload: models.ShipmentCancelRequest
|
38
|
+
) -> lib.Serializable[str]:
|
39
|
+
return provider.shipment_cancel_request(payload, self.settings)
|
40
|
+
|
41
|
+
def parse_cancel_pickup_response(
|
42
|
+
self, response: lib.Deserializable[str]
|
43
|
+
) -> typing.Tuple[models.ConfirmationDetails, typing.List[models.Message]]:
|
44
|
+
return provider.parse_pickup_cancel_response(response, self.settings)
|
45
|
+
|
46
|
+
def parse_cancel_shipment_response(
|
47
|
+
self, response: lib.Deserializable[str]
|
48
|
+
) -> typing.Tuple[models.ConfirmationDetails, typing.List[models.Message]]:
|
49
|
+
return provider.parse_shipment_cancel_response(response, self.settings)
|
50
|
+
|
51
|
+
def parse_pickup_response(
|
52
|
+
self, response: lib.Deserializable[str]
|
53
|
+
) -> typing.Tuple[models.PickupDetails, typing.List[models.Message]]:
|
54
|
+
return provider.parse_pickup_response(response, self.settings)
|
55
|
+
|
56
|
+
def parse_pickup_update_response(
|
57
|
+
self, response: lib.Deserializable[str]
|
58
|
+
) -> typing.Tuple[models.PickupDetails, typing.List[models.Message]]:
|
59
|
+
return provider.parse_pickup_update_response(response, self.settings)
|
60
|
+
|
61
|
+
def parse_rate_response(
|
62
|
+
self, response: lib.Deserializable[str]
|
63
|
+
) -> typing.Tuple[typing.List[models.RateDetails], typing.List[models.Message]]:
|
64
|
+
return universal_provider.parse_rate_response(response, self.settings)
|
65
|
+
|
66
|
+
def parse_shipment_response(
|
67
|
+
self, response: lib.Deserializable[str]
|
68
|
+
) -> typing.Tuple[models.ShipmentDetails, typing.List[models.Message]]:
|
69
|
+
return provider.parse_shipment_response(response, self.settings)
|
@@ -0,0 +1,87 @@
|
|
1
|
+
"""Karrio SAPIENT client proxy."""
|
2
|
+
|
3
|
+
import karrio.lib as lib
|
4
|
+
import karrio.api.proxy as proxy
|
5
|
+
import karrio.providers.sapient.utils as provider_utils
|
6
|
+
import karrio.mappers.sapient.settings as provider_settings
|
7
|
+
import karrio.universal.mappers.rating_proxy as rating_proxy
|
8
|
+
|
9
|
+
|
10
|
+
class Proxy(rating_proxy.RatingMixinProxy, proxy.Proxy):
|
11
|
+
settings: provider_settings.Settings
|
12
|
+
|
13
|
+
def get_rates(self, request: lib.Serializable) -> lib.Deserializable[str]:
|
14
|
+
return super().get_rates(request)
|
15
|
+
|
16
|
+
def create_shipment(self, request: lib.Serializable) -> lib.Deserializable[str]:
|
17
|
+
response = lib.request(
|
18
|
+
url=f"{self.settings.server_url}/v4/shipments/{request.ctx['carrier_code']}",
|
19
|
+
data=lib.to_json(request.serialize()),
|
20
|
+
trace=self.trace_as("json"),
|
21
|
+
method="POST",
|
22
|
+
headers={
|
23
|
+
"Content-Type": "application/json",
|
24
|
+
"Authorization": f"Bearer {self.settings.access_token}",
|
25
|
+
"user-agent": "Karrio/1.0",
|
26
|
+
},
|
27
|
+
on_error=provider_utils.parse_error_response,
|
28
|
+
)
|
29
|
+
|
30
|
+
return lib.Deserializable(response, lib.to_dict, request.ctx)
|
31
|
+
|
32
|
+
def cancel_shipment(self, request: lib.Serializable) -> lib.Deserializable[str]:
|
33
|
+
response = lib.request(
|
34
|
+
url=f"{self.settings.server_url}/v4/shipments/status",
|
35
|
+
data=lib.to_json(request.serialize()),
|
36
|
+
trace=self.trace_as("json"),
|
37
|
+
method="PUT",
|
38
|
+
headers={
|
39
|
+
"Content-Type": "application/json",
|
40
|
+
"Authorization": f"Bearer {self.settings.access_token}",
|
41
|
+
"user-agent": "Karrio/1.0",
|
42
|
+
},
|
43
|
+
on_ok=lambda _: '{"ok": true}',
|
44
|
+
on_error=provider_utils.parse_error_response,
|
45
|
+
)
|
46
|
+
|
47
|
+
return lib.Deserializable(response, lib.to_dict)
|
48
|
+
|
49
|
+
def schedule_pickup(self, request: lib.Serializable) -> lib.Deserializable[str]:
|
50
|
+
response = lib.request(
|
51
|
+
url=f"{self.settings.server_url}/v4/collections/{request.ctx['carrier_code']}/{request.ctx['shipmentId']}",
|
52
|
+
data=lib.to_json(request.serialize()),
|
53
|
+
trace=self.trace_as("json"),
|
54
|
+
method="POST",
|
55
|
+
headers={
|
56
|
+
"Content-Type": "application/json",
|
57
|
+
"Authorization": f"Bearer {self.settings.access_token}",
|
58
|
+
"user-agent": "Karrio/1.0",
|
59
|
+
},
|
60
|
+
on_error=provider_utils.parse_error_response,
|
61
|
+
)
|
62
|
+
|
63
|
+
return lib.Deserializable(response, lib.to_dict, request.ctx)
|
64
|
+
|
65
|
+
def modify_pickup(self, request: lib.Serializable) -> lib.Deserializable[str]:
|
66
|
+
response = self.cancel_pickup(lib.Serializable(request.ctx))
|
67
|
+
|
68
|
+
if response.deserialize()["ok"]:
|
69
|
+
response = self.schedule_pickup(request)
|
70
|
+
|
71
|
+
return lib.Deserializable(response, lib.to_dict, request.ctx)
|
72
|
+
|
73
|
+
def cancel_pickup(self, request: lib.Serializable) -> lib.Deserializable[str]:
|
74
|
+
payload = request.serialize()
|
75
|
+
response = lib.request(
|
76
|
+
url=f"{self.settings.server_url}/v4/collections/{payload['carrier_code']}/{payload['shipmentId']}/cancel",
|
77
|
+
trace=self.trace_as("json"),
|
78
|
+
method="PUT",
|
79
|
+
headers={
|
80
|
+
"Content-Type": "application/json",
|
81
|
+
"Authorization": f"Bearer {self.settings.access_token}",
|
82
|
+
"user-agent": "Karrio/1.0",
|
83
|
+
},
|
84
|
+
on_error=provider_utils.parse_error_response,
|
85
|
+
)
|
86
|
+
|
87
|
+
return lib.Deserializable(response, lib.to_dict)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
"""Karrio SAPIENT client settings."""
|
2
|
+
|
3
|
+
import attr
|
4
|
+
import typing
|
5
|
+
import jstruct
|
6
|
+
import karrio.core.models as models
|
7
|
+
import karrio.providers.sapient.utils as provider_utils
|
8
|
+
import karrio.providers.sapient.units as provider_units
|
9
|
+
|
10
|
+
|
11
|
+
@attr.s(auto_attribs=True)
|
12
|
+
class Settings(provider_utils.Settings):
|
13
|
+
"""SAPIENT connection settings."""
|
14
|
+
|
15
|
+
# Add carrier specific API connection properties here
|
16
|
+
client_id: str
|
17
|
+
client_secret: str
|
18
|
+
shipping_account_id: str
|
19
|
+
sapient_carrier_code: provider_utils.SapientCarrierCode = "RM" # type: ignore
|
20
|
+
|
21
|
+
# generic properties
|
22
|
+
id: str = None
|
23
|
+
test_mode: bool = False
|
24
|
+
carrier_id: str = "sapient"
|
25
|
+
account_country_code: str = "GB"
|
26
|
+
metadata: dict = {}
|
27
|
+
config: dict = {}
|
28
|
+
|
29
|
+
services: typing.List[models.ServiceLevel] = jstruct.JList[models.ServiceLevel, False, dict(default=provider_units.DEFAULT_SERVICES)] # type: ignore
|
30
|
+
|
31
|
+
@property
|
32
|
+
def shipping_services(self) -> typing.List[models.ServiceLevel]:
|
33
|
+
if any(self.services or []):
|
34
|
+
return self.services
|
35
|
+
|
36
|
+
return provider_units.DEFAULT_SERVICES
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import karrio.core.metadata as metadata
|
2
|
+
import karrio.mappers.sapient as mappers
|
3
|
+
import karrio.providers.sapient.units as units
|
4
|
+
import karrio.providers.sapient.utils as utils
|
5
|
+
|
6
|
+
|
7
|
+
METADATA = metadata.PluginMetadata(
|
8
|
+
status="production-ready",
|
9
|
+
id="sapient",
|
10
|
+
label="SAPIENT",
|
11
|
+
# Integrations
|
12
|
+
Mapper=mappers.Mapper,
|
13
|
+
Proxy=mappers.Proxy,
|
14
|
+
Settings=mappers.Settings,
|
15
|
+
# Data Units
|
16
|
+
is_hub=True,
|
17
|
+
options=units.ShippingOption,
|
18
|
+
services=units.ShippingService,
|
19
|
+
connection_configs=utils.ConnectionConfig,
|
20
|
+
)
|
@@ -0,0 +1,18 @@
|
|
1
|
+
"""Karrio SAPIENT provider imports."""
|
2
|
+
|
3
|
+
from karrio.providers.sapient.utils import Settings
|
4
|
+
|
5
|
+
from karrio.providers.sapient.shipment import (
|
6
|
+
parse_shipment_cancel_response,
|
7
|
+
parse_shipment_response,
|
8
|
+
shipment_cancel_request,
|
9
|
+
shipment_request,
|
10
|
+
)
|
11
|
+
from karrio.providers.sapient.pickup import (
|
12
|
+
parse_pickup_cancel_response,
|
13
|
+
parse_pickup_update_response,
|
14
|
+
parse_pickup_response,
|
15
|
+
pickup_update_request,
|
16
|
+
pickup_cancel_request,
|
17
|
+
pickup_request,
|
18
|
+
)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
"""Karrio SAPIENT error parser."""
|
2
|
+
|
3
|
+
import typing
|
4
|
+
import karrio.lib as lib
|
5
|
+
import karrio.core.models as models
|
6
|
+
import karrio.providers.sapient.utils as provider_utils
|
7
|
+
|
8
|
+
|
9
|
+
def parse_error_response(
|
10
|
+
response: typing.Union[dict, typing.List[dict]],
|
11
|
+
settings: provider_utils.Settings,
|
12
|
+
**kwargs,
|
13
|
+
) -> typing.List[models.Message]:
|
14
|
+
responses = response if isinstance(response, list) else [response]
|
15
|
+
errors: typing.List[dict] = sum(
|
16
|
+
[_["Errors"] for _ in responses if "Errors" in _], []
|
17
|
+
)
|
18
|
+
|
19
|
+
return [
|
20
|
+
models.Message(
|
21
|
+
carrier_id=settings.carrier_id,
|
22
|
+
carrier_name=settings.carrier_name,
|
23
|
+
code=error.get("ErrorCode", "UNKNOWN"),
|
24
|
+
message=error.get("Message", "Unknown error"),
|
25
|
+
details=lib.to_dict({**kwargs, "Cause": error.get("Cause")}),
|
26
|
+
)
|
27
|
+
for error in errors
|
28
|
+
]
|
@@ -0,0 +1,4 @@
|
|
1
|
+
|
2
|
+
from karrio.providers.sapient.pickup.create import parse_pickup_response, pickup_request
|
3
|
+
from karrio.providers.sapient.pickup.update import parse_pickup_update_response, pickup_update_request
|
4
|
+
from karrio.providers.sapient.pickup.cancel import parse_pickup_cancel_response, pickup_cancel_request
|
@@ -0,0 +1,57 @@
|
|
1
|
+
import typing
|
2
|
+
import karrio.lib as lib
|
3
|
+
import karrio.core.units as units
|
4
|
+
import karrio.core.models as models
|
5
|
+
import karrio.providers.sapient.error as error
|
6
|
+
import karrio.providers.sapient.utils as provider_utils
|
7
|
+
import karrio.providers.sapient.units as provider_units
|
8
|
+
|
9
|
+
|
10
|
+
def parse_pickup_cancel_response(
|
11
|
+
_response: lib.Deserializable[dict],
|
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
|
+
success = True # compute address validation success state
|
17
|
+
|
18
|
+
confirmation = (
|
19
|
+
models.ConfirmationDetails(
|
20
|
+
carrier_id=settings.carrier_id,
|
21
|
+
carrier_name=settings.carrier_name,
|
22
|
+
operation="Cancel Pickup",
|
23
|
+
success=success,
|
24
|
+
)
|
25
|
+
if success
|
26
|
+
else None
|
27
|
+
)
|
28
|
+
|
29
|
+
return confirmation, messages
|
30
|
+
|
31
|
+
|
32
|
+
def pickup_cancel_request(
|
33
|
+
payload: models.PickupCancelRequest,
|
34
|
+
settings: provider_utils.Settings,
|
35
|
+
) -> lib.Serializable:
|
36
|
+
options = lib.units.Options(
|
37
|
+
payload.options,
|
38
|
+
option_type=lib.units.create_enum(
|
39
|
+
"PickupOptions",
|
40
|
+
# fmt: off
|
41
|
+
{
|
42
|
+
"sapient_carrier_code": lib.OptionEnum("sapient_carrier_code"),
|
43
|
+
"sapient_shipment_id": lib.OptionEnum("sapient_shipment_id"),
|
44
|
+
},
|
45
|
+
# fmt: on
|
46
|
+
),
|
47
|
+
)
|
48
|
+
|
49
|
+
# map data to convert karrio model to sapient specific type
|
50
|
+
request = dict(
|
51
|
+
shipmentId=options.sapient_shipment_id.state,
|
52
|
+
carrier_code=lib.identity(
|
53
|
+
options.sapient_carrier_code.state or settings.sapient_carrier_code
|
54
|
+
),
|
55
|
+
)
|
56
|
+
|
57
|
+
return lib.Serializable(request, lib.to_dict)
|
@@ -0,0 +1,87 @@
|
|
1
|
+
import karrio.schemas.sapient.pickup_request as sapient
|
2
|
+
import karrio.schemas.sapient.pickup_response as pickup
|
3
|
+
|
4
|
+
import typing
|
5
|
+
import karrio.lib as lib
|
6
|
+
import karrio.core.units as units
|
7
|
+
import karrio.core.models as models
|
8
|
+
import karrio.providers.sapient.error as error
|
9
|
+
import karrio.providers.sapient.utils as provider_utils
|
10
|
+
import karrio.providers.sapient.units as provider_units
|
11
|
+
|
12
|
+
|
13
|
+
def parse_pickup_response(
|
14
|
+
_response: lib.Deserializable[dict],
|
15
|
+
settings: provider_utils.Settings,
|
16
|
+
) -> typing.Tuple[typing.List[models.PickupDetails], typing.List[models.Message]]:
|
17
|
+
response = _response.deserialize()
|
18
|
+
|
19
|
+
messages = error.parse_error_response(response, settings)
|
20
|
+
pickup = lib.identity(
|
21
|
+
_extract_details(response, settings, _response.ctx)
|
22
|
+
if "CollectionOrderId" in response
|
23
|
+
else None
|
24
|
+
)
|
25
|
+
|
26
|
+
return pickup, messages
|
27
|
+
|
28
|
+
|
29
|
+
def _extract_details(
|
30
|
+
data: dict,
|
31
|
+
settings: provider_utils.Settings,
|
32
|
+
ctx: dict = None,
|
33
|
+
) -> models.PickupDetails:
|
34
|
+
details = lib.to_object(pickup.PickupResponseType, data)
|
35
|
+
|
36
|
+
return models.PickupDetails(
|
37
|
+
carrier_id=settings.carrier_id,
|
38
|
+
carrier_name=settings.carrier_name,
|
39
|
+
confirmation_number=details.CollectionOrderId,
|
40
|
+
pickup_date=lib.fdate(details.CollectionDate),
|
41
|
+
meta=dict(
|
42
|
+
sapient_shipment_id=ctx.get("shipmentId"),
|
43
|
+
sapient_carrier_code=ctx.get("carrier_code"),
|
44
|
+
),
|
45
|
+
)
|
46
|
+
|
47
|
+
|
48
|
+
def pickup_request(
|
49
|
+
payload: models.PickupRequest,
|
50
|
+
settings: provider_utils.Settings,
|
51
|
+
) -> lib.Serializable:
|
52
|
+
options = lib.units.Options(
|
53
|
+
payload.options,
|
54
|
+
option_type=lib.units.create_enum(
|
55
|
+
"PickupOptions",
|
56
|
+
# fmt: off
|
57
|
+
{
|
58
|
+
"sapient_shipment_id": lib.OptionEnum("sapient_shipment_id"),
|
59
|
+
"sapient_carrier_code": lib.OptionEnum("sapient_carrier_code"),
|
60
|
+
"sapient_bring_my_label": lib.OptionEnum("BringMyLabel"),
|
61
|
+
"sapient_slot_reservation_id": lib.OptionEnum("SlotReservationId"),
|
62
|
+
},
|
63
|
+
# fmt: on
|
64
|
+
),
|
65
|
+
)
|
66
|
+
|
67
|
+
# map data to convert karrio model to sapient specific type
|
68
|
+
request = sapient.PickupRequestType(
|
69
|
+
SlotDate=payload.pickup_date,
|
70
|
+
SlotReservationId=options.sapient_slot_reservation_id.state,
|
71
|
+
BringMyLabel=lib.identity(
|
72
|
+
options.sapient_bring_my_label.state
|
73
|
+
if options.sapient_bring_my_label.state is not None
|
74
|
+
else False
|
75
|
+
),
|
76
|
+
)
|
77
|
+
|
78
|
+
return lib.Serializable(
|
79
|
+
request,
|
80
|
+
lib.to_dict,
|
81
|
+
dict(
|
82
|
+
shipmentId=options.sapient_shipment_id.state,
|
83
|
+
carrier_code=lib.identity(
|
84
|
+
options.sapient_carrier_code.state or settings.sapient_carrier_code
|
85
|
+
),
|
86
|
+
),
|
87
|
+
)
|
@@ -0,0 +1,87 @@
|
|
1
|
+
import karrio.schemas.sapient.pickup_request as sapient
|
2
|
+
import karrio.schemas.sapient.pickup_response as pickup
|
3
|
+
|
4
|
+
import typing
|
5
|
+
import karrio.lib as lib
|
6
|
+
import karrio.core.units as units
|
7
|
+
import karrio.core.models as models
|
8
|
+
import karrio.providers.sapient.error as error
|
9
|
+
import karrio.providers.sapient.utils as provider_utils
|
10
|
+
import karrio.providers.sapient.units as provider_units
|
11
|
+
|
12
|
+
|
13
|
+
def parse_pickup_update_response(
|
14
|
+
_response: lib.Deserializable[dict],
|
15
|
+
settings: provider_utils.Settings,
|
16
|
+
) -> typing.Tuple[typing.List[models.PickupDetails], typing.List[models.Message]]:
|
17
|
+
response = _response.deserialize()
|
18
|
+
|
19
|
+
messages = error.parse_error_response(response, settings, _response.ctx)
|
20
|
+
pickup = lib.identity(
|
21
|
+
_extract_details(response, settings)
|
22
|
+
if "confirmation_number" in response
|
23
|
+
else None
|
24
|
+
)
|
25
|
+
|
26
|
+
return pickup, messages
|
27
|
+
|
28
|
+
|
29
|
+
def _extract_details(
|
30
|
+
data: dict,
|
31
|
+
settings: provider_utils.Settings,
|
32
|
+
ctx: dict = None,
|
33
|
+
) -> models.PickupDetails:
|
34
|
+
details = lib.to_object(pickup.PickupResponseType, data)
|
35
|
+
|
36
|
+
return models.PickupDetails(
|
37
|
+
carrier_id=settings.carrier_id,
|
38
|
+
carrier_name=settings.carrier_name,
|
39
|
+
confirmation_number=details.CollectionOrderId,
|
40
|
+
pickup_date=lib.fdate(details.CollectionDate),
|
41
|
+
meta=dict(
|
42
|
+
sapient_shipment_id=ctx.get("shipmentId"),
|
43
|
+
sapient_carrier_code=ctx.get("carrier_code"),
|
44
|
+
),
|
45
|
+
)
|
46
|
+
|
47
|
+
|
48
|
+
def pickup_update_request(
|
49
|
+
payload: models.PickupUpdateRequest,
|
50
|
+
settings: provider_utils.Settings,
|
51
|
+
) -> lib.Serializable:
|
52
|
+
options = lib.units.Options(
|
53
|
+
payload.options,
|
54
|
+
option_type=lib.units.create_enum(
|
55
|
+
"PickupOptions",
|
56
|
+
# fmt: off
|
57
|
+
{
|
58
|
+
"sapient_shipment_id": lib.OptionEnum("shipment_id"),
|
59
|
+
"sapient_carrier_code": lib.OptionEnum("sapient_carrier_code"),
|
60
|
+
"sapient_slot_reservation_id": lib.OptionEnum("SlotReservationId"),
|
61
|
+
"sapient_bring_my_label": lib.OptionEnum("BringMyLabel", bool),
|
62
|
+
},
|
63
|
+
# fmt: on
|
64
|
+
),
|
65
|
+
)
|
66
|
+
|
67
|
+
# map data to convert karrio model to sapient specific type
|
68
|
+
request = sapient.PickupRequestType(
|
69
|
+
SlotDate=payload.pickup_date,
|
70
|
+
SlotReservationId=options.sapient_slot_reservation_id.state,
|
71
|
+
BringMyLabel=lib.identity(
|
72
|
+
options.sapient_bring_my_label.state
|
73
|
+
if options.sapient_bring_my_label.state is not None
|
74
|
+
else False
|
75
|
+
),
|
76
|
+
)
|
77
|
+
|
78
|
+
return lib.Serializable(
|
79
|
+
request,
|
80
|
+
lib.to_dict,
|
81
|
+
dict(
|
82
|
+
shipmentId=options.sapient_shipment_id.state,
|
83
|
+
carrier_code=lib.identity(
|
84
|
+
options.sapient_carrier_code.state or settings.sapient_carrier_code
|
85
|
+
),
|
86
|
+
),
|
87
|
+
)
|
@@ -0,0 +1,57 @@
|
|
1
|
+
import typing
|
2
|
+
import karrio.lib as lib
|
3
|
+
import karrio.core.models as models
|
4
|
+
import karrio.providers.sapient.error as error
|
5
|
+
import karrio.providers.sapient.utils as provider_utils
|
6
|
+
import karrio.providers.sapient.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
|
+
messages = error.parse_error_response(response, settings)
|
15
|
+
success = response.get("ok") is True
|
16
|
+
|
17
|
+
confirmation = (
|
18
|
+
models.ConfirmationDetails(
|
19
|
+
carrier_id=settings.carrier_id,
|
20
|
+
carrier_name=settings.carrier_name,
|
21
|
+
operation="Cancel Shipment",
|
22
|
+
success=success,
|
23
|
+
)
|
24
|
+
if success
|
25
|
+
else None
|
26
|
+
)
|
27
|
+
|
28
|
+
return confirmation, messages
|
29
|
+
|
30
|
+
|
31
|
+
def shipment_cancel_request(
|
32
|
+
payload: models.ShipmentCancelRequest,
|
33
|
+
settings: provider_utils.Settings,
|
34
|
+
) -> lib.Serializable:
|
35
|
+
options = lib.units.Options(
|
36
|
+
payload.options,
|
37
|
+
option_type=lib.units.create_enum(
|
38
|
+
"PickupOptions",
|
39
|
+
# fmt: off
|
40
|
+
{
|
41
|
+
"reason": lib.OptionEnum("Reason"),
|
42
|
+
"shipment_ids": lib.OptionEnum("ShipmentIds", list),
|
43
|
+
},
|
44
|
+
# fmt: on
|
45
|
+
),
|
46
|
+
)
|
47
|
+
|
48
|
+
# map data to convert karrio model to sapient specific type
|
49
|
+
request = dict(
|
50
|
+
Status="Cancel",
|
51
|
+
Reason=options.reason.state or "Order Cancelled",
|
52
|
+
ShipmentIds=lib.identity(
|
53
|
+
options.shipment_ids.state or [payload.shipment_identifier]
|
54
|
+
),
|
55
|
+
)
|
56
|
+
|
57
|
+
return lib.Serializable(request, lib.to_dict)
|