karrio-dicom 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/dicom/__init__.py +3 -0
- karrio/mappers/dicom/mapper.py +107 -0
- karrio/mappers/dicom/proxy.py +31 -0
- karrio/mappers/dicom/settings.py +22 -0
- karrio/plugins/dicom/__init__.py +16 -0
- karrio/providers/dicom/__init__.py +20 -0
- karrio/providers/dicom/error.py +19 -0
- karrio/providers/dicom/pickup/__init__.py +3 -0
- karrio/providers/dicom/pickup/cancel.py +33 -0
- karrio/providers/dicom/pickup/create.py +102 -0
- karrio/providers/dicom/pickup/update.py +57 -0
- karrio/providers/dicom/rate.py +127 -0
- karrio/providers/dicom/shipment/__init__.py +2 -0
- karrio/providers/dicom/shipment/cancel.py +32 -0
- karrio/providers/dicom/shipment/create.py +192 -0
- karrio/providers/dicom/tracking.py +47 -0
- karrio/providers/dicom/units.py +167 -0
- karrio/providers/dicom/utils.py +34 -0
- karrio/schemas/dicom/__init__.py +0 -0
- karrio/schemas/dicom/pickups.py +83 -0
- karrio/schemas/dicom/rates.py +126 -0
- karrio/schemas/dicom/shipments.py +140 -0
- karrio/schemas/dicom/tracking.py +58 -0
- karrio_dicom-2025.5rc1.dist-info/METADATA +44 -0
- karrio_dicom-2025.5rc1.dist-info/RECORD +28 -0
- karrio_dicom-2025.5rc1.dist-info/WHEEL +5 -0
- karrio_dicom-2025.5rc1.dist-info/entry_points.txt +2 -0
- karrio_dicom-2025.5rc1.dist-info/top_level.txt +3 -0
@@ -0,0 +1,107 @@
|
|
1
|
+
from typing import List, Tuple
|
2
|
+
from karrio.core.utils.serializable import Serializable, Deserializable
|
3
|
+
from karrio.api.mapper import Mapper as BaseMapper
|
4
|
+
from karrio.core.models import (
|
5
|
+
# ShipmentCancelRequest,
|
6
|
+
# PickupUpdateRequest,
|
7
|
+
# PickupCancelRequest,
|
8
|
+
# ShipmentRequest,
|
9
|
+
TrackingRequest,
|
10
|
+
# PickupRequest,
|
11
|
+
# RateRequest,
|
12
|
+
#
|
13
|
+
# ConfirmationDetails,
|
14
|
+
TrackingDetails,
|
15
|
+
# ShipmentDetails,
|
16
|
+
# PickupDetails,
|
17
|
+
# RateDetails,
|
18
|
+
Message,
|
19
|
+
)
|
20
|
+
from karrio.providers.dicom import (
|
21
|
+
# parse_shipment_cancel_response,
|
22
|
+
# parse_pickup_update_response,
|
23
|
+
# parse_pickup_cancel_response,
|
24
|
+
# parse_shipment_response,
|
25
|
+
parse_tracking_response,
|
26
|
+
# parse_pickup_response,
|
27
|
+
# parse_rate_response,
|
28
|
+
#
|
29
|
+
# shipment_cancel_request,
|
30
|
+
# pickup_update_request,
|
31
|
+
# pickup_cancel_request,
|
32
|
+
tracking_request,
|
33
|
+
# shipment_request,
|
34
|
+
# pickup_request,
|
35
|
+
# rate_request,
|
36
|
+
)
|
37
|
+
from karrio.mappers.dicom.settings import Settings
|
38
|
+
|
39
|
+
|
40
|
+
class Mapper(BaseMapper):
|
41
|
+
settings: Settings
|
42
|
+
|
43
|
+
# def create_rate_request(
|
44
|
+
# self, payload: RateRequest
|
45
|
+
# ) -> Serializable:
|
46
|
+
# return rate_request(payload, self.settings)
|
47
|
+
|
48
|
+
def create_tracking_request(self, payload: TrackingRequest) -> Serializable:
|
49
|
+
return tracking_request(payload, self.settings)
|
50
|
+
|
51
|
+
# def create_shipment_request(
|
52
|
+
# self, payload: ShipmentRequest
|
53
|
+
# ) -> Serializable:
|
54
|
+
# return shipment_request(payload, self.settings)
|
55
|
+
#
|
56
|
+
# def create_pickup_request(
|
57
|
+
# self, payload: PickupRequest
|
58
|
+
# ) -> Serializable:
|
59
|
+
# return pickup_request(payload, self.settings)
|
60
|
+
#
|
61
|
+
# def create_pickup_update_request(
|
62
|
+
# self, payload: PickupUpdateRequest
|
63
|
+
# ) -> Serializable:
|
64
|
+
# return pickup_update_request(payload, self.settings)
|
65
|
+
#
|
66
|
+
# def create_cancel_pickup_request(
|
67
|
+
# self, payload: PickupCancelRequest
|
68
|
+
# ) -> Serializable:
|
69
|
+
# return pickup_cancel_request(payload, self.settings)
|
70
|
+
#
|
71
|
+
# def create_cancel_shipment_request(self, payload: ShipmentCancelRequest) -> Serializable:
|
72
|
+
# return shipment_cancel_request(payload, self.settings)
|
73
|
+
|
74
|
+
# def parse_cancel_pickup_response(
|
75
|
+
# self, response: Deserializable
|
76
|
+
# ) -> Tuple[ConfirmationDetails, List[Message]]:
|
77
|
+
# return parse_pickup_cancel_response(response, self.settings)
|
78
|
+
#
|
79
|
+
# def parse_cancel_shipment_response(
|
80
|
+
# self, response: Deserializable
|
81
|
+
# ) -> Tuple[ConfirmationDetails, List[Message]]:
|
82
|
+
# return parse_shipment_cancel_response(response, self.settings)
|
83
|
+
#
|
84
|
+
# def parse_pickup_response(
|
85
|
+
# self, response: Deserializable
|
86
|
+
# ) -> Tuple[PickupDetails, List[Message]]:
|
87
|
+
# return parse_pickup_response(response, self.settings)
|
88
|
+
#
|
89
|
+
# def parse_pickup_update_response(
|
90
|
+
# self, response: Deserializable
|
91
|
+
# ) -> Tuple[PickupDetails, List[Message]]:
|
92
|
+
# return parse_pickup_update_response(response, self.settings)
|
93
|
+
#
|
94
|
+
# def parse_rate_response(
|
95
|
+
# self, response: Deserializable
|
96
|
+
# ) -> Tuple[List[RateDetails], List[Message]]:
|
97
|
+
# return parse_rate_response(response, self.settings)
|
98
|
+
#
|
99
|
+
# def parse_shipment_response(
|
100
|
+
# self, response: Deserializable
|
101
|
+
# ) -> Tuple[ShipmentDetails, List[Message]]:
|
102
|
+
# return parse_shipment_response(response, self.settings)
|
103
|
+
|
104
|
+
def parse_tracking_response(
|
105
|
+
self, response: Deserializable
|
106
|
+
) -> Tuple[List[TrackingDetails], List[Message]]:
|
107
|
+
return parse_tracking_response(response, self.settings)
|
@@ -0,0 +1,31 @@
|
|
1
|
+
from typing import List
|
2
|
+
from karrio.core.utils import (
|
3
|
+
Serializable,
|
4
|
+
Deserializable,
|
5
|
+
request as http,
|
6
|
+
exec_async,
|
7
|
+
DP,
|
8
|
+
)
|
9
|
+
from karrio.api.proxy import Proxy as BaseProxy
|
10
|
+
from karrio.mappers.dicom.settings import Settings
|
11
|
+
|
12
|
+
|
13
|
+
class Proxy(BaseProxy):
|
14
|
+
settings: Settings
|
15
|
+
|
16
|
+
def get_tracking(self, request: Serializable) -> Deserializable:
|
17
|
+
def _get_tracking(tracking_number: str):
|
18
|
+
return http(
|
19
|
+
url=f"{self.settings.server_url}/v1/tracking/{tracking_number}",
|
20
|
+
trace=self.trace_as("json"),
|
21
|
+
method="GET",
|
22
|
+
headers={
|
23
|
+
"Accept": "application/json",
|
24
|
+
"Authorization": f"Basic {self.settings.authorization}",
|
25
|
+
},
|
26
|
+
)
|
27
|
+
|
28
|
+
responses: List[dict] = exec_async(_get_tracking, request.serialize())
|
29
|
+
return Deserializable(
|
30
|
+
responses, lambda res: [DP.to_dict(r) for r in res if any(r.strip())]
|
31
|
+
)
|
@@ -0,0 +1,22 @@
|
|
1
|
+
"""Karrio Dicom client settings."""
|
2
|
+
|
3
|
+
import attr
|
4
|
+
from karrio.providers.dicom.utils import Settings as BaseSettings
|
5
|
+
|
6
|
+
|
7
|
+
@attr.s(auto_attribs=True)
|
8
|
+
class Settings(BaseSettings):
|
9
|
+
"""Dicom connection settings."""
|
10
|
+
|
11
|
+
# Carrier specific properties
|
12
|
+
username: str
|
13
|
+
password: str
|
14
|
+
billing_account: str = None
|
15
|
+
|
16
|
+
# Base properties
|
17
|
+
id: str = None
|
18
|
+
test_mode: bool = False
|
19
|
+
carrier_id: str = "dicom"
|
20
|
+
account_country_code: str = None
|
21
|
+
metadata: dict = {}
|
22
|
+
config: dict = {}
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import karrio.core.metadata as metadata
|
2
|
+
import karrio.mappers.dicom as mappers
|
3
|
+
|
4
|
+
|
5
|
+
METADATA = metadata.PluginMetadata(
|
6
|
+
status="beta",
|
7
|
+
id="dicom",
|
8
|
+
label="Dicom",
|
9
|
+
|
10
|
+
# Integrations
|
11
|
+
Mapper=mappers.Mapper,
|
12
|
+
Proxy=mappers.Proxy,
|
13
|
+
Settings=mappers.Settings,
|
14
|
+
|
15
|
+
# Data Units
|
16
|
+
)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# from karrio.providers.dicom.utils import Settings
|
2
|
+
# from karrio.providers.dicom.rate import parse_rate_response, rate_request
|
3
|
+
# from karrio.providers.dicom.shipment import (
|
4
|
+
# parse_shipment_cancel_response,
|
5
|
+
# parse_shipment_response,
|
6
|
+
# shipment_cancel_request,
|
7
|
+
# shipment_request,
|
8
|
+
# )
|
9
|
+
# from karrio.providers.dicom.pickup import (
|
10
|
+
# parse_pickup_cancel_response,
|
11
|
+
# parse_pickup_update_response,
|
12
|
+
# parse_pickup_response,
|
13
|
+
# pickup_update_request,
|
14
|
+
# pickup_cancel_request,
|
15
|
+
# pickup_request,
|
16
|
+
# )
|
17
|
+
from karrio.providers.dicom.tracking import (
|
18
|
+
parse_tracking_response,
|
19
|
+
tracking_request,
|
20
|
+
)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
from typing import List
|
2
|
+
from karrio.providers.sendle import Settings
|
3
|
+
from karrio.core.models import Message
|
4
|
+
|
5
|
+
|
6
|
+
def parse_error_response(response: List[dict], settings: Settings) -> List[Message]:
|
7
|
+
return [_extract_error(e, settings) for e in response]
|
8
|
+
|
9
|
+
|
10
|
+
def _extract_error(carrier_error: dict, settings: Settings) -> Message:
|
11
|
+
return Message(
|
12
|
+
# context info
|
13
|
+
carrier_name=settings.carrier_name,
|
14
|
+
carrier_id=settings.carrier_id,
|
15
|
+
|
16
|
+
# carrier error info
|
17
|
+
code=carrier_error.get('Code'),
|
18
|
+
message=carrier_error.get('Message')
|
19
|
+
)
|
@@ -0,0 +1,3 @@
|
|
1
|
+
from karrio.providers.dicom.pickup.create import parse_pickup_response, pickup_request
|
2
|
+
from karrio.providers.dicom.pickup.update import parse_pickup_update_response, pickup_update_request
|
3
|
+
from karrio.providers.dicom.pickup.cancel import parse_pickup_cancel_response, pickup_cancel_request
|
@@ -0,0 +1,33 @@
|
|
1
|
+
from typing import Tuple, List
|
2
|
+
from karrio.core.utils import Serializable
|
3
|
+
from karrio.core.models import PickupCancelRequest, ConfirmationDetails, Message
|
4
|
+
|
5
|
+
from karrio.providers.dicom.error import parse_error_response
|
6
|
+
from karrio.providers.dicom.utils import Settings
|
7
|
+
import karrio.lib as lib
|
8
|
+
|
9
|
+
|
10
|
+
def parse_pickup_cancel_response(
|
11
|
+
_response: lib.Deserializable[dict],
|
12
|
+
settings: Settings,
|
13
|
+
) -> Tuple[ConfirmationDetails, List[Message]]:
|
14
|
+
response = _response.deserialize()
|
15
|
+
errors = parse_error_response(response, settings)
|
16
|
+
details = (
|
17
|
+
ConfirmationDetails(
|
18
|
+
carrier_id=settings.carrier_id,
|
19
|
+
carrier_name=settings.carrier_name,
|
20
|
+
success=True,
|
21
|
+
operation="Pickup Cancel",
|
22
|
+
)
|
23
|
+
if not any(errors)
|
24
|
+
else None
|
25
|
+
)
|
26
|
+
|
27
|
+
return details, errors
|
28
|
+
|
29
|
+
|
30
|
+
def pickup_cancel_request(payload: PickupCancelRequest, _) -> Serializable:
|
31
|
+
request = payload.confirmation_number
|
32
|
+
|
33
|
+
return Serializable(request)
|
@@ -0,0 +1,102 @@
|
|
1
|
+
import urllib.parse
|
2
|
+
from typing import Tuple, List
|
3
|
+
from functools import partial
|
4
|
+
from karrio.schemas.dicom.pickups import (
|
5
|
+
PickupRequest as DicomPickupRequest,
|
6
|
+
Sender,
|
7
|
+
Contact,
|
8
|
+
Pickup,
|
9
|
+
)
|
10
|
+
from karrio.core.utils import Serializable, Pipeline, Job, DP, SF
|
11
|
+
from karrio.core.models import PickupRequest, PickupDetails, Message
|
12
|
+
|
13
|
+
from karrio.providers.dicom.error import parse_error_response
|
14
|
+
from karrio.providers.dicom.utils import Settings
|
15
|
+
import karrio.lib as lib
|
16
|
+
|
17
|
+
|
18
|
+
def parse_pickup_response(
|
19
|
+
_response: lib.Deserializable[dict], settings: Settings
|
20
|
+
) -> Tuple[PickupDetails, List[Message]]:
|
21
|
+
response = _response.deserialize()
|
22
|
+
errors = parse_error_response(response, settings)
|
23
|
+
pickup = next(
|
24
|
+
(DP.to_object(Pickup, pickup) for pickup in response.get("pickups", [])), None
|
25
|
+
)
|
26
|
+
details = _extract_details(pickup, settings) if pickup is not None else None
|
27
|
+
|
28
|
+
return details, errors
|
29
|
+
|
30
|
+
|
31
|
+
def _extract_details(pickup: Pickup, settings: Settings) -> PickupDetails:
|
32
|
+
return PickupDetails(
|
33
|
+
carrier_id=settings.carrier_id,
|
34
|
+
carrier_name=settings.carrier_name,
|
35
|
+
confirmation_number=str(pickup.id),
|
36
|
+
closing_time=pickup.officeClose,
|
37
|
+
pickup_date=pickup.date,
|
38
|
+
ready_time=pickup.ready,
|
39
|
+
)
|
40
|
+
|
41
|
+
|
42
|
+
def pickup_request(payload: PickupRequest, settings: Settings) -> Serializable:
|
43
|
+
request: Pipeline = Pipeline(
|
44
|
+
create_pickup=lambda *_: _create_pickup(payload),
|
45
|
+
retrieve_pickup=partial(_retrieve_pickup, payload=payload, settings=settings),
|
46
|
+
)
|
47
|
+
|
48
|
+
return Serializable(request)
|
49
|
+
|
50
|
+
|
51
|
+
def _create_pickup(payload: PickupRequest) -> Job:
|
52
|
+
request = DicomPickupRequest(
|
53
|
+
date=payload.pickup_date,
|
54
|
+
ready=payload.ready_time,
|
55
|
+
category=payload.options.get("category", "Parcel"),
|
56
|
+
officeClose=payload.closing_time,
|
57
|
+
sender=Sender(
|
58
|
+
city=payload.address.city,
|
59
|
+
provinceCode=payload.address.state_code,
|
60
|
+
postalCode=payload.address.postal_code,
|
61
|
+
countryCode=payload.address.country_code,
|
62
|
+
customerName=payload.address.company_name,
|
63
|
+
streetNumber=payload.address.street_number,
|
64
|
+
contact=Contact(
|
65
|
+
fullName=payload.address.person_name,
|
66
|
+
email=payload.address.email,
|
67
|
+
telephone=payload.address.phone_number,
|
68
|
+
),
|
69
|
+
),
|
70
|
+
location=payload.options.get("dicom_location", "OT"),
|
71
|
+
otherLocation=payload.package_location,
|
72
|
+
)
|
73
|
+
|
74
|
+
return Job(id="create_pickup", data=Serializable(request, DP.to_dict))
|
75
|
+
|
76
|
+
|
77
|
+
def _retrieve_pickup(
|
78
|
+
creation_response: str, payload: PickupRequest, settings: Settings
|
79
|
+
) -> Job:
|
80
|
+
errors = parse_error_response(DP.to_dict(creation_response), settings)
|
81
|
+
data = (
|
82
|
+
Serializable(
|
83
|
+
dict(
|
84
|
+
category=payload.options.get("category", "Parcel"),
|
85
|
+
pickupDate=payload.pickup_date,
|
86
|
+
streetNumber=SF.concat_str(
|
87
|
+
payload.address.address_line1,
|
88
|
+
payload.address.address_line2,
|
89
|
+
join=True,
|
90
|
+
),
|
91
|
+
postalCode=payload.address.postal_code,
|
92
|
+
offset=10,
|
93
|
+
),
|
94
|
+
urllib.parse.urlencode,
|
95
|
+
)
|
96
|
+
if not any(errors)
|
97
|
+
else None
|
98
|
+
)
|
99
|
+
|
100
|
+
return Job(
|
101
|
+
id="retrieve_pickup", data=data, fallback=("{}" if data is None else None)
|
102
|
+
)
|
@@ -0,0 +1,57 @@
|
|
1
|
+
from typing import Tuple, List, cast
|
2
|
+
from functools import partial
|
3
|
+
from karrio.core.utils import Serializable, Pipeline, Job
|
4
|
+
from karrio.core.models import (
|
5
|
+
PickupCancelRequest,
|
6
|
+
PickupUpdateRequest,
|
7
|
+
PickupRequest,
|
8
|
+
PickupDetails,
|
9
|
+
Message,
|
10
|
+
)
|
11
|
+
|
12
|
+
from karrio.providers.dicom.pickup.create import (
|
13
|
+
_create_pickup as _create_pickup_job,
|
14
|
+
parse_pickup_response,
|
15
|
+
_retrieve_pickup,
|
16
|
+
)
|
17
|
+
from karrio.providers.dicom.pickup.cancel import pickup_cancel_request
|
18
|
+
from karrio.providers.dicom.error import parse_error_response
|
19
|
+
from karrio.providers.dicom.utils import Settings
|
20
|
+
import karrio.lib as lib
|
21
|
+
|
22
|
+
|
23
|
+
def parse_pickup_update_response(
|
24
|
+
_response: lib.Deserializable[dict], settings: Settings
|
25
|
+
) -> Tuple[PickupDetails, List[Message]]:
|
26
|
+
response = _response.deserialize()
|
27
|
+
return parse_pickup_response(response, settings)
|
28
|
+
|
29
|
+
|
30
|
+
def pickup_update_request(
|
31
|
+
payload: PickupUpdateRequest, settings: Settings
|
32
|
+
) -> Serializable:
|
33
|
+
request: Pipeline = Pipeline(
|
34
|
+
delete_pickup=lambda *_: _delete_pickup(payload, settings),
|
35
|
+
create_pickup=partial(_create_pickup_job, payload=payload, settings=settings),
|
36
|
+
retrieve_pickup=partial(_retrieve_pickup, payload=payload, settings=settings),
|
37
|
+
)
|
38
|
+
|
39
|
+
return Serializable(request)
|
40
|
+
|
41
|
+
|
42
|
+
def _delete_pickup(payload: PickupUpdateRequest, settings: Settings) -> Job:
|
43
|
+
data = pickup_cancel_request(
|
44
|
+
settings=settings, payload=cast(PickupCancelRequest, payload)
|
45
|
+
)
|
46
|
+
|
47
|
+
return Job(id="delete_pickup", data=data)
|
48
|
+
|
49
|
+
|
50
|
+
def _create_pickup(deletion_response: str, payload: PickupUpdateRequest) -> Job:
|
51
|
+
errors = parse_error_response(deletion_response)
|
52
|
+
create_job: Job = (
|
53
|
+
_create_pickup_job(cast(PickupRequest, payload)) if not any(errors) else None
|
54
|
+
)
|
55
|
+
data = create_job.data if create_job is not None else None
|
56
|
+
|
57
|
+
return Job(id="create_pickup", data=data, fallback=("{}" if data is None else None))
|
@@ -0,0 +1,127 @@
|
|
1
|
+
from karrio.schemas.dicom.rates import (
|
2
|
+
RateRequest as DicomRateRequest,
|
3
|
+
Address,
|
4
|
+
Parcel,
|
5
|
+
Surcharge,
|
6
|
+
Rate,
|
7
|
+
RateResponse,
|
8
|
+
)
|
9
|
+
|
10
|
+
import typing
|
11
|
+
import karrio.lib as lib
|
12
|
+
import karrio.core.models as models
|
13
|
+
import karrio.providers.dicom.error as provider_error
|
14
|
+
import karrio.providers.dicom.units as provider_units
|
15
|
+
import karrio.providers.dicom.utils as provider_utils
|
16
|
+
|
17
|
+
|
18
|
+
def parse_rate_response(
|
19
|
+
_response: lib.Deserializable[dict], settings: provider_utils.Settings
|
20
|
+
) -> typing.Tuple[typing.List[models.RateDetails], typing.List[models.Message]]:
|
21
|
+
response = _response.deserialize()
|
22
|
+
errors = provider_error.parse_error_response(response, settings)
|
23
|
+
rate_response = (
|
24
|
+
lib.to_object(RateResponse, response) if "rates" in response else RateResponse()
|
25
|
+
)
|
26
|
+
details = [
|
27
|
+
_extract_details(rate, rate_response, settings)
|
28
|
+
for rate in (rate_response.rates or [])
|
29
|
+
]
|
30
|
+
|
31
|
+
return details, errors
|
32
|
+
|
33
|
+
|
34
|
+
def _extract_details(
|
35
|
+
rate: Rate, response: RateResponse, settings: provider_utils.Settings
|
36
|
+
) -> models.RateDetails:
|
37
|
+
charges = [
|
38
|
+
("Base Charge", rate.basicCharge),
|
39
|
+
("Discount", rate.discountAmount),
|
40
|
+
("Taxes", rate.taxes),
|
41
|
+
*((charge.name, charge.amount) for charge in rate.surcharges),
|
42
|
+
]
|
43
|
+
|
44
|
+
return models.RateDetails(
|
45
|
+
carrier_id=settings.carrier_id,
|
46
|
+
carrier_name=settings.carrier_name,
|
47
|
+
currency="CAD",
|
48
|
+
transit_days=response.delay,
|
49
|
+
service=provider_units.Service(rate.rateType),
|
50
|
+
total_charge=lib.to_decimal(rate.total),
|
51
|
+
extra_charges=[
|
52
|
+
provider_units.ChargeDetails(
|
53
|
+
currency="CAD",
|
54
|
+
name=name,
|
55
|
+
amount=lib.to_decimal(charge),
|
56
|
+
)
|
57
|
+
for name, charge in charges
|
58
|
+
if charge
|
59
|
+
],
|
60
|
+
meta=dict(accountType=rate.accountType),
|
61
|
+
)
|
62
|
+
|
63
|
+
|
64
|
+
def rate_request(
|
65
|
+
payload: models.RateRequest, settings: provider_utils.Settings
|
66
|
+
) -> lib.Serializable:
|
67
|
+
packages = lib.to_packages(payload.parcels)
|
68
|
+
service = (
|
69
|
+
provider_units.Services(payload.services, provider_units.Service).first
|
70
|
+
or provider_units.Service.dicom_ground_delivery.value
|
71
|
+
).value
|
72
|
+
options = lib.to_shipping_options(
|
73
|
+
payload.options,
|
74
|
+
package_options=packages.options,
|
75
|
+
initializer=provider_units.shipping_options_initializer,
|
76
|
+
)
|
77
|
+
|
78
|
+
request = DicomRateRequest(
|
79
|
+
category="Parcel",
|
80
|
+
paymentType=provider_units.PaymentType.prepaid.value,
|
81
|
+
deliveryType=service,
|
82
|
+
unitOfMeasurement=provider_units.UnitOfMeasurement.KC.value,
|
83
|
+
sender=Address(
|
84
|
+
postalCode=payload.shipper.postal_code,
|
85
|
+
provinceCode=payload.shipper.state_code,
|
86
|
+
countryCode=payload.shipper.country_code,
|
87
|
+
name=(payload.shipper.company_name or payload.shipper.person_name),
|
88
|
+
),
|
89
|
+
consignee=Address(
|
90
|
+
postalCode=payload.recipient.postal_code,
|
91
|
+
provinceCode=payload.recipient.state_code,
|
92
|
+
countryCode=payload.recipient.country_code,
|
93
|
+
name=(payload.recipient.company_name or payload.recipient.person_name),
|
94
|
+
),
|
95
|
+
parcels=[
|
96
|
+
Parcel(
|
97
|
+
quantity=1,
|
98
|
+
parcelType=provider_units.ParcelType[
|
99
|
+
package.packaging_type or "dicom_box"
|
100
|
+
].value,
|
101
|
+
id=None,
|
102
|
+
weight=package.weight.KG,
|
103
|
+
length=package.height.CM,
|
104
|
+
depth=package.length.CM,
|
105
|
+
width=package.width.CM,
|
106
|
+
note=None,
|
107
|
+
status=None,
|
108
|
+
FCA_Class=None,
|
109
|
+
hazmat=None,
|
110
|
+
requestReturnLabel=None,
|
111
|
+
returnWaybill=None,
|
112
|
+
)
|
113
|
+
for package in packages
|
114
|
+
],
|
115
|
+
billing=settings.billing_account,
|
116
|
+
promoCodes=None,
|
117
|
+
surcharges=[
|
118
|
+
Surcharge(
|
119
|
+
type=option.code,
|
120
|
+
value=lib.to_money(option.state),
|
121
|
+
)
|
122
|
+
for _, option in options.items()
|
123
|
+
],
|
124
|
+
appointment=None,
|
125
|
+
)
|
126
|
+
|
127
|
+
return lib.Serializable(request, lib.to_dict)
|
@@ -0,0 +1,32 @@
|
|
1
|
+
from typing import Tuple, List
|
2
|
+
from karrio.core.utils import Serializable
|
3
|
+
from karrio.core.models import ShipmentCancelRequest, ConfirmationDetails, Message
|
4
|
+
|
5
|
+
from karrio.providers.dicom.error import parse_error_response
|
6
|
+
from karrio.providers.dicom.utils import Settings
|
7
|
+
import karrio.lib as lib
|
8
|
+
|
9
|
+
|
10
|
+
def parse_shipment_cancel_response(
|
11
|
+
response: lib.Deserializable[dict],
|
12
|
+
settings: Settings,
|
13
|
+
) -> Tuple[ConfirmationDetails, List[Message]]:
|
14
|
+
errors = parse_error_response(response, settings)
|
15
|
+
details = (
|
16
|
+
ConfirmationDetails(
|
17
|
+
carrier_id=settings.carrier_id,
|
18
|
+
carrier_name=settings.carrier_name,
|
19
|
+
operation="Shipment Cancel",
|
20
|
+
success=True,
|
21
|
+
)
|
22
|
+
if not any(errors)
|
23
|
+
else None
|
24
|
+
)
|
25
|
+
|
26
|
+
return details, errors
|
27
|
+
|
28
|
+
|
29
|
+
def shipment_cancel_request(payload: ShipmentCancelRequest, _) -> Serializable:
|
30
|
+
request = payload.shipment_identifier
|
31
|
+
|
32
|
+
return Serializable(request)
|