karrio-seko 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/seko/__init__.py +3 -0
- karrio/mappers/seko/mapper.py +64 -0
- karrio/mappers/seko/proxy.py +88 -0
- karrio/mappers/seko/settings.py +20 -0
- karrio/plugins/seko/__init__.py +20 -0
- karrio/providers/seko/__init__.py +17 -0
- karrio/providers/seko/error.py +73 -0
- karrio/providers/seko/manifest.py +62 -0
- karrio/providers/seko/rate.py +107 -0
- karrio/providers/seko/shipment/__init__.py +9 -0
- karrio/providers/seko/shipment/cancel.py +61 -0
- karrio/providers/seko/shipment/create.py +224 -0
- karrio/providers/seko/tracking.py +95 -0
- karrio/providers/seko/units.py +239 -0
- karrio/providers/seko/utils.py +114 -0
- karrio/schemas/seko/__init__.py +0 -0
- karrio/schemas/seko/error_response.py +11 -0
- karrio/schemas/seko/manifest_response.py +19 -0
- karrio/schemas/seko/rating_request.py +46 -0
- karrio/schemas/seko/rating_response.py +41 -0
- karrio/schemas/seko/shipping_request.py +131 -0
- karrio/schemas/seko/shipping_response.py +79 -0
- karrio/schemas/seko/tracking_response.py +24 -0
- karrio_seko-2025.5rc1.dist-info/METADATA +45 -0
- karrio_seko-2025.5rc1.dist-info/RECORD +28 -0
- karrio_seko-2025.5rc1.dist-info/WHEEL +5 -0
- karrio_seko-2025.5rc1.dist-info/entry_points.txt +2 -0
- karrio_seko-2025.5rc1.dist-info/top_level.txt +3 -0
@@ -0,0 +1,64 @@
|
|
1
|
+
"""Karrio SEKO Logistics 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.seko as provider
|
8
|
+
import karrio.mappers.seko.settings as provider_settings
|
9
|
+
|
10
|
+
|
11
|
+
class Mapper(mapper.Mapper):
|
12
|
+
settings: provider_settings.Settings
|
13
|
+
|
14
|
+
def create_rate_request(
|
15
|
+
self, payload: models.RateRequest
|
16
|
+
) -> lib.Serializable:
|
17
|
+
return provider.rate_request(payload, self.settings)
|
18
|
+
|
19
|
+
def create_tracking_request(
|
20
|
+
self, payload: models.TrackingRequest
|
21
|
+
) -> lib.Serializable:
|
22
|
+
return provider.tracking_request(payload, self.settings)
|
23
|
+
|
24
|
+
def create_shipment_request(
|
25
|
+
self, payload: models.ShipmentRequest
|
26
|
+
) -> lib.Serializable:
|
27
|
+
return provider.shipment_request(payload, self.settings)
|
28
|
+
|
29
|
+
def create_cancel_shipment_request(
|
30
|
+
self, payload: models.ShipmentCancelRequest
|
31
|
+
) -> lib.Serializable[str]:
|
32
|
+
return provider.shipment_cancel_request(payload, self.settings)
|
33
|
+
|
34
|
+
def create_manifest_request(
|
35
|
+
self, payload: models.ManifestRequest
|
36
|
+
) -> lib.Serializable:
|
37
|
+
return provider.manifest_request(payload, self.settings)
|
38
|
+
|
39
|
+
|
40
|
+
def parse_cancel_shipment_response(
|
41
|
+
self, response: lib.Deserializable[str]
|
42
|
+
) -> typing.Tuple[models.ConfirmationDetails, typing.List[models.Message]]:
|
43
|
+
return provider.parse_shipment_cancel_response(response, self.settings)
|
44
|
+
|
45
|
+
def parse_rate_response(
|
46
|
+
self, response: lib.Deserializable[str]
|
47
|
+
) -> typing.Tuple[typing.List[models.RateDetails], typing.List[models.Message]]:
|
48
|
+
return provider.parse_rate_response(response, self.settings)
|
49
|
+
|
50
|
+
def parse_shipment_response(
|
51
|
+
self, response: lib.Deserializable[str]
|
52
|
+
) -> typing.Tuple[models.ShipmentDetails, typing.List[models.Message]]:
|
53
|
+
return provider.parse_shipment_response(response, self.settings)
|
54
|
+
|
55
|
+
def parse_tracking_response(
|
56
|
+
self, response: lib.Deserializable[str]
|
57
|
+
) -> typing.Tuple[typing.List[models.TrackingDetails], typing.List[models.Message]]:
|
58
|
+
return provider.parse_tracking_response(response, self.settings)
|
59
|
+
|
60
|
+
def parse_manifest_response(
|
61
|
+
self, response: lib.Deserializable[str]
|
62
|
+
) -> typing.Tuple[models.ManifestDetails, typing.List[models.Message]]:
|
63
|
+
return provider.parse_manifest_response(response, self.settings)
|
64
|
+
|
@@ -0,0 +1,88 @@
|
|
1
|
+
"""Karrio SEKO Logistics client proxy."""
|
2
|
+
|
3
|
+
import karrio.lib as lib
|
4
|
+
import karrio.api.proxy as proxy
|
5
|
+
import karrio.providers.seko.utils as provider_utils
|
6
|
+
import karrio.mappers.seko.settings as provider_settings
|
7
|
+
|
8
|
+
|
9
|
+
class Proxy(proxy.Proxy):
|
10
|
+
settings: provider_settings.Settings
|
11
|
+
|
12
|
+
def get_rates(self, request: lib.Serializable) -> lib.Deserializable[str]:
|
13
|
+
response = lib.request(
|
14
|
+
url=f"{self.settings.server_url}/ratesqueryv1/availablerates",
|
15
|
+
data=lib.to_json(request.serialize()),
|
16
|
+
trace=self.trace_as("json"),
|
17
|
+
method="POST",
|
18
|
+
headers={
|
19
|
+
"Content-Type": "application/json; charset=utf-8",
|
20
|
+
"access_key": f"{self.settings.access_key}",
|
21
|
+
},
|
22
|
+
on_error=provider_utils.parse_error_response,
|
23
|
+
)
|
24
|
+
|
25
|
+
return lib.Deserializable(response, lib.to_dict)
|
26
|
+
|
27
|
+
def create_shipment(self, request: lib.Serializable) -> lib.Deserializable[str]:
|
28
|
+
response = lib.request(
|
29
|
+
url=f"{self.settings.server_url}/labels/printshipment",
|
30
|
+
data=lib.to_json(request.serialize()),
|
31
|
+
trace=self.trace_as("json"),
|
32
|
+
method="POST",
|
33
|
+
headers={
|
34
|
+
"Content-Type": "application/json; charset=utf-8",
|
35
|
+
"access_key": f"{self.settings.access_key}",
|
36
|
+
},
|
37
|
+
on_error=provider_utils.parse_error_response,
|
38
|
+
)
|
39
|
+
|
40
|
+
return lib.Deserializable(response, lib.to_dict, request.ctx)
|
41
|
+
|
42
|
+
def cancel_shipment(self, request: lib.Serializable) -> lib.Deserializable[str]:
|
43
|
+
response = lib.request(
|
44
|
+
url=f"{self.settings.server_url}/labels/delete",
|
45
|
+
data=lib.to_json(request.serialize()),
|
46
|
+
trace=self.trace_as("json"),
|
47
|
+
method="POST",
|
48
|
+
headers={
|
49
|
+
"Content-Type": "application/json; charset=utf-8",
|
50
|
+
"access_key": f"{self.settings.access_key}",
|
51
|
+
},
|
52
|
+
on_error=provider_utils.parse_error_response,
|
53
|
+
)
|
54
|
+
|
55
|
+
return lib.Deserializable(
|
56
|
+
response,
|
57
|
+
lib.to_dict,
|
58
|
+
)
|
59
|
+
|
60
|
+
def get_tracking(self, request: lib.Serializable) -> lib.Deserializable[str]:
|
61
|
+
response = lib.request(
|
62
|
+
url=f"{self.settings.server_url}/labels/statusv2",
|
63
|
+
data=lib.to_json(request.serialize()),
|
64
|
+
trace=self.trace_as("json"),
|
65
|
+
method="POST",
|
66
|
+
headers={
|
67
|
+
"Content-Type": "application/json; charset=utf-8",
|
68
|
+
"access_key": f"{self.settings.access_key}",
|
69
|
+
},
|
70
|
+
on_error=provider_utils.parse_error_response,
|
71
|
+
)
|
72
|
+
|
73
|
+
return lib.Deserializable(response, lib.to_dict)
|
74
|
+
|
75
|
+
def create_manifest(self, request: lib.Serializable) -> lib.Deserializable[str]:
|
76
|
+
response = lib.request(
|
77
|
+
url=f"{self.settings.server_url}/v2/publishmanifestv4",
|
78
|
+
data=lib.to_json(request.serialize()),
|
79
|
+
trace=self.trace_as("json"),
|
80
|
+
method="POST",
|
81
|
+
headers={
|
82
|
+
"Content-Type": "application/json; charset=utf-8",
|
83
|
+
"access_key": f"{self.settings.access_key}",
|
84
|
+
},
|
85
|
+
on_error=provider_utils.parse_error_response,
|
86
|
+
)
|
87
|
+
|
88
|
+
return lib.Deserializable(response, lib.to_dict)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
"""Karrio SEKO Logistics client settings."""
|
2
|
+
|
3
|
+
import attr
|
4
|
+
import karrio.providers.seko.utils as provider_utils
|
5
|
+
|
6
|
+
|
7
|
+
@attr.s(auto_attribs=True)
|
8
|
+
class Settings(provider_utils.Settings):
|
9
|
+
"""SEKO Logistics connection settings."""
|
10
|
+
|
11
|
+
# Add carrier specific API connection properties here
|
12
|
+
access_key: str
|
13
|
+
|
14
|
+
# generic properties
|
15
|
+
id: str = None
|
16
|
+
test_mode: bool = False
|
17
|
+
carrier_id: str = "seko"
|
18
|
+
account_country_code: str = None
|
19
|
+
metadata: dict = {}
|
20
|
+
config: dict = {}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
import karrio.core.metadata as metadata
|
2
|
+
import karrio.mappers.seko as mappers
|
3
|
+
import karrio.providers.seko.units as units
|
4
|
+
import karrio.providers.seko.utils as utils
|
5
|
+
|
6
|
+
|
7
|
+
METADATA = metadata.PluginMetadata(
|
8
|
+
status="production-ready",
|
9
|
+
id="seko",
|
10
|
+
label="SEKO Logistics",
|
11
|
+
# Integrations
|
12
|
+
Mapper=mappers.Mapper,
|
13
|
+
Proxy=mappers.Proxy,
|
14
|
+
Settings=mappers.Settings,
|
15
|
+
# Data Units
|
16
|
+
is_hub=False,
|
17
|
+
options=units.ShippingOption,
|
18
|
+
services=units.ShippingService,
|
19
|
+
connection_configs=utils.ConnectionConfig,
|
20
|
+
)
|
@@ -0,0 +1,17 @@
|
|
1
|
+
"""Karrio SEKO Logistics provider imports."""
|
2
|
+
from karrio.providers.seko.utils import Settings
|
3
|
+
from karrio.providers.seko.rate import parse_rate_response, rate_request
|
4
|
+
from karrio.providers.seko.shipment import (
|
5
|
+
parse_shipment_cancel_response,
|
6
|
+
parse_shipment_response,
|
7
|
+
shipment_cancel_request,
|
8
|
+
shipment_request,
|
9
|
+
)
|
10
|
+
from karrio.providers.seko.tracking import (
|
11
|
+
parse_tracking_response,
|
12
|
+
tracking_request,
|
13
|
+
)
|
14
|
+
from karrio.providers.seko.manifest import (
|
15
|
+
parse_manifest_response,
|
16
|
+
manifest_request,
|
17
|
+
)
|
@@ -0,0 +1,73 @@
|
|
1
|
+
"""Karrio SEKO Logistics error parser."""
|
2
|
+
|
3
|
+
import typing
|
4
|
+
import karrio.lib as lib
|
5
|
+
import karrio.core.models as models
|
6
|
+
import karrio.providers.seko.utils as provider_utils
|
7
|
+
|
8
|
+
|
9
|
+
def parse_error_response(
|
10
|
+
response: typing.Union[typing.List[dict], dict],
|
11
|
+
settings: provider_utils.Settings,
|
12
|
+
**kwargs,
|
13
|
+
) -> typing.List[models.Message]:
|
14
|
+
responses = response if isinstance(response, list) else [response]
|
15
|
+
errors: list = []
|
16
|
+
|
17
|
+
for response_item in responses:
|
18
|
+
if validation_errors := response_item.get("ValidationErrors"):
|
19
|
+
if isinstance(validation_errors, dict):
|
20
|
+
errors.append(
|
21
|
+
{
|
22
|
+
"code": "ValidationError",
|
23
|
+
"message": validation_errors.get(
|
24
|
+
"Message", next(iter(validation_errors.values()))
|
25
|
+
),
|
26
|
+
**{
|
27
|
+
k: v for k, v in validation_errors.items() if k != "Message"
|
28
|
+
},
|
29
|
+
}
|
30
|
+
)
|
31
|
+
else:
|
32
|
+
errors.append(
|
33
|
+
{"code": "ValidationError", "message": str(validation_errors)}
|
34
|
+
)
|
35
|
+
break
|
36
|
+
|
37
|
+
if rejected := response_item.get("Rejected", []):
|
38
|
+
error = rejected[0]
|
39
|
+
errors.append(
|
40
|
+
{
|
41
|
+
"code": "Rejected",
|
42
|
+
"message": error.get("Reason"),
|
43
|
+
**{k: v for k, v in error.items() if k != "Reason"},
|
44
|
+
}
|
45
|
+
)
|
46
|
+
break
|
47
|
+
|
48
|
+
if general_errors := (
|
49
|
+
response_item.get("Errors", []) or response_item.get("Error", [])
|
50
|
+
):
|
51
|
+
error = general_errors[0]
|
52
|
+
errors.append(
|
53
|
+
{
|
54
|
+
"code": "Error",
|
55
|
+
"message": error.get("Message"),
|
56
|
+
**{k: v for k, v in error.items() if k != "Message"},
|
57
|
+
}
|
58
|
+
)
|
59
|
+
break
|
60
|
+
|
61
|
+
return [
|
62
|
+
models.Message(
|
63
|
+
carrier_id=settings.carrier_id,
|
64
|
+
carrier_name=settings.carrier_name,
|
65
|
+
code=error["code"],
|
66
|
+
message=error["message"],
|
67
|
+
details={
|
68
|
+
**kwargs,
|
69
|
+
**{k: v for k, v in error.items() if k not in ["code", "message"]},
|
70
|
+
},
|
71
|
+
)
|
72
|
+
for error in errors
|
73
|
+
]
|
@@ -0,0 +1,62 @@
|
|
1
|
+
"""Karrio SEKO Logistics manifest API implementation."""
|
2
|
+
|
3
|
+
import karrio.schemas.seko.manifest_response as manifest
|
4
|
+
|
5
|
+
import typing
|
6
|
+
import karrio.lib as lib
|
7
|
+
import karrio.core.models as models
|
8
|
+
import karrio.providers.seko.error as error
|
9
|
+
import karrio.providers.seko.utils as provider_utils
|
10
|
+
import karrio.providers.seko.units as provider_units
|
11
|
+
|
12
|
+
|
13
|
+
def parse_manifest_response(
|
14
|
+
_response: lib.Deserializable[dict],
|
15
|
+
settings: provider_utils.Settings,
|
16
|
+
) -> typing.Tuple[models.ManifestDetails, typing.List[models.Message]]:
|
17
|
+
response = _response.deserialize()
|
18
|
+
|
19
|
+
messages = error.parse_error_response(response, settings)
|
20
|
+
details = lib.identity(
|
21
|
+
_extract_details(response, settings)
|
22
|
+
if any(response.get("OutboundManifest") or [])
|
23
|
+
else None
|
24
|
+
)
|
25
|
+
|
26
|
+
return details, messages
|
27
|
+
|
28
|
+
|
29
|
+
def _extract_details(
|
30
|
+
data: dict,
|
31
|
+
settings: provider_utils.Settings,
|
32
|
+
) -> models.ManifestDetails:
|
33
|
+
details = lib.to_object(manifest.ManifestResponseType, data)
|
34
|
+
manifest_numbers = [_.ManifestNumber for _ in details.OutboundManifest]
|
35
|
+
manifest_connotes: list = sum(
|
36
|
+
[_.ManifestedConnotes for _ in details.OutboundManifest], []
|
37
|
+
)
|
38
|
+
manifest_doc = lib.bundle_base64(
|
39
|
+
[_.ManifestContent for _ in details.OutboundManifest], "PDF"
|
40
|
+
)
|
41
|
+
|
42
|
+
return models.ManifestDetails(
|
43
|
+
carrier_id=settings.carrier_id,
|
44
|
+
carrier_name=settings.carrier_id,
|
45
|
+
doc=models.ManifestDocument(manifest=manifest_doc),
|
46
|
+
meta=dict(
|
47
|
+
ManifestNumber=manifest_numbers[0],
|
48
|
+
ManifestNumbers=manifest_numbers,
|
49
|
+
ManifestConnotes=manifest_connotes,
|
50
|
+
),
|
51
|
+
)
|
52
|
+
|
53
|
+
|
54
|
+
def manifest_request(
|
55
|
+
payload: models.ManifestRequest,
|
56
|
+
settings: provider_utils.Settings,
|
57
|
+
) -> lib.Serializable:
|
58
|
+
|
59
|
+
# map data to convert karrio model to seko specific type
|
60
|
+
request = payload.shipment_identifiers
|
61
|
+
|
62
|
+
return lib.Serializable(request, lib.to_dict)
|
@@ -0,0 +1,107 @@
|
|
1
|
+
"""Karrio SEKO Logistics rating API implementation."""
|
2
|
+
|
3
|
+
import karrio.schemas.seko.rating_request as seko
|
4
|
+
import karrio.schemas.seko.rating_response as rating
|
5
|
+
|
6
|
+
import typing
|
7
|
+
import karrio.lib as lib
|
8
|
+
import karrio.core.units as units
|
9
|
+
import karrio.core.models as models
|
10
|
+
import karrio.providers.seko.error as error
|
11
|
+
import karrio.providers.seko.utils as provider_utils
|
12
|
+
import karrio.providers.seko.units as provider_units
|
13
|
+
|
14
|
+
|
15
|
+
def parse_rate_response(
|
16
|
+
_response: lib.Deserializable[dict],
|
17
|
+
settings: provider_utils.Settings,
|
18
|
+
) -> typing.Tuple[typing.List[models.RateDetails], typing.List[models.Message]]:
|
19
|
+
response = _response.deserialize()
|
20
|
+
|
21
|
+
messages = error.parse_error_response(response, settings)
|
22
|
+
rates = [_extract_details(rate, settings) for rate in response.get("Available", [])]
|
23
|
+
|
24
|
+
return rates, messages
|
25
|
+
|
26
|
+
|
27
|
+
def _extract_details(
|
28
|
+
data: dict,
|
29
|
+
settings: provider_utils.Settings,
|
30
|
+
) -> models.RateDetails:
|
31
|
+
details = lib.to_object(rating.AvailableType, data)
|
32
|
+
service = provider_units.ShippingService.map(details.DeliveryType)
|
33
|
+
|
34
|
+
return models.RateDetails(
|
35
|
+
carrier_id=settings.carrier_id,
|
36
|
+
carrier_name=settings.carrier_name,
|
37
|
+
service=service.name_or_key,
|
38
|
+
total_charge=lib.to_money(details.Cost),
|
39
|
+
currency=settings.connection_config.currency.state or "USD",
|
40
|
+
meta=dict(
|
41
|
+
service_name=service.value_or_key,
|
42
|
+
seko_carrier=details.CarrierName,
|
43
|
+
Route=details.Route,
|
44
|
+
QuoteId=details.QuoteId,
|
45
|
+
DeliveryType=details.DeliveryType,
|
46
|
+
CarrierServiceType=details.CarrierServiceType,
|
47
|
+
IsFreightForward=details.IsFreightForward,
|
48
|
+
IsRuralDelivery=details.IsRuralDelivery,
|
49
|
+
IsSaturdayDelivery=details.IsSaturdayDelivery,
|
50
|
+
),
|
51
|
+
)
|
52
|
+
|
53
|
+
|
54
|
+
def rate_request(
|
55
|
+
payload: models.RateRequest,
|
56
|
+
settings: provider_utils.Settings,
|
57
|
+
) -> lib.Serializable:
|
58
|
+
recipient = lib.to_address(payload.recipient)
|
59
|
+
options = lib.to_shipping_options(
|
60
|
+
payload.options,
|
61
|
+
initializer=provider_units.shipping_options_initializer,
|
62
|
+
)
|
63
|
+
packages = lib.to_packages(
|
64
|
+
payload.parcels,
|
65
|
+
options=options,
|
66
|
+
shipping_options_initializer=provider_units.shipping_options_initializer,
|
67
|
+
)
|
68
|
+
|
69
|
+
# map data to convert karrio model to seko specific type
|
70
|
+
request = seko.RatingRequestType(
|
71
|
+
DeliveryReference=payload.reference,
|
72
|
+
Destination=seko.DestinationType(
|
73
|
+
Id=options.seko_destination_id.state,
|
74
|
+
Name=recipient.company_name,
|
75
|
+
Address=seko.AddressType(
|
76
|
+
BuildingName="",
|
77
|
+
StreetAddress=recipient.street,
|
78
|
+
Suburb=recipient.city,
|
79
|
+
City=recipient.state_code,
|
80
|
+
PostCode=recipient.postal_code,
|
81
|
+
CountryCode=recipient.country_code,
|
82
|
+
),
|
83
|
+
ContactPerson=recipient.contact,
|
84
|
+
PhoneNumber=recipient.phone_number,
|
85
|
+
Email=recipient.email,
|
86
|
+
DeliveryInstructions=options.destination_instructions.state,
|
87
|
+
RecipientTaxId=recipient.tax_id,
|
88
|
+
),
|
89
|
+
IsSaturdayDelivery=options.seko_is_saturday_delivery.state,
|
90
|
+
IsSignatureRequired=options.seko_is_signature_required.state,
|
91
|
+
Packages=[
|
92
|
+
seko.PackageType(
|
93
|
+
Height=package.height.CM,
|
94
|
+
Length=package.length.CM,
|
95
|
+
Id=package.options.seko_package_id.state,
|
96
|
+
Width=package.width.CM,
|
97
|
+
Kg=package.weight.KG,
|
98
|
+
Name=lib.text(package.description, max=50),
|
99
|
+
Type=provider_units.PackagingType.map(
|
100
|
+
package.packaging_type or "your_packaging"
|
101
|
+
).value,
|
102
|
+
)
|
103
|
+
for package in packages
|
104
|
+
],
|
105
|
+
)
|
106
|
+
|
107
|
+
return lib.Serializable(request, lib.to_dict)
|
@@ -0,0 +1,61 @@
|
|
1
|
+
import typing
|
2
|
+
import karrio.lib as lib
|
3
|
+
import karrio.core.models as models
|
4
|
+
import karrio.providers.seko.error as error
|
5
|
+
import karrio.providers.seko.utils as provider_utils
|
6
|
+
import karrio.providers.seko.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(
|
15
|
+
dict(
|
16
|
+
Errors=[
|
17
|
+
{"ConsignmentId": _, "Message": __}
|
18
|
+
for _, __ in response.items()
|
19
|
+
if isinstance(__, str) and "Deleted" not in __
|
20
|
+
]
|
21
|
+
),
|
22
|
+
settings,
|
23
|
+
)
|
24
|
+
success = any(["Deleted" in _ for _ in response.values() if isinstance(_, str)])
|
25
|
+
|
26
|
+
confirmation = (
|
27
|
+
models.ConfirmationDetails(
|
28
|
+
carrier_id=settings.carrier_id,
|
29
|
+
carrier_name=settings.carrier_name,
|
30
|
+
operation="Cancel Shipment",
|
31
|
+
success=success,
|
32
|
+
)
|
33
|
+
if success
|
34
|
+
else None
|
35
|
+
)
|
36
|
+
|
37
|
+
return confirmation, messages
|
38
|
+
|
39
|
+
|
40
|
+
def shipment_cancel_request(
|
41
|
+
payload: models.ShipmentCancelRequest,
|
42
|
+
settings: provider_utils.Settings,
|
43
|
+
) -> lib.Serializable:
|
44
|
+
options = lib.units.Options(
|
45
|
+
payload.options,
|
46
|
+
option_type=lib.units.create_enum(
|
47
|
+
"PickupOptions",
|
48
|
+
# fmt: off
|
49
|
+
{
|
50
|
+
"shipment_identifiers": lib.OptionEnum("shipment_identifiers", lib.to_list),
|
51
|
+
},
|
52
|
+
# fmt: on
|
53
|
+
),
|
54
|
+
)
|
55
|
+
|
56
|
+
# map data to convert karrio model to seko specific type
|
57
|
+
request = lib.identity(
|
58
|
+
options.shipment_identifiers.state or [payload.shipment_identifier]
|
59
|
+
)
|
60
|
+
|
61
|
+
return lib.Serializable(request, lib.to_dict)
|