karrio-geodis 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/geodis/__init__.py +3 -0
- karrio/mappers/geodis/mapper.py +51 -0
- karrio/mappers/geodis/proxy.py +76 -0
- karrio/mappers/geodis/settings.py +36 -0
- karrio/plugins/geodis/__init__.py +20 -0
- karrio/providers/geodis/__init__.py +11 -0
- karrio/providers/geodis/error.py +29 -0
- karrio/providers/geodis/shipment/__init__.py +8 -0
- karrio/providers/geodis/shipment/cancel.py +39 -0
- karrio/providers/geodis/shipment/create.py +202 -0
- karrio/providers/geodis/tracking.py +96 -0
- karrio/providers/geodis/units.py +248 -0
- karrio/providers/geodis/utils.py +58 -0
- karrio/schemas/geodis/__init__.py +0 -0
- karrio/schemas/geodis/cancel_request.py +10 -0
- karrio/schemas/geodis/cancel_response.py +73 -0
- karrio/schemas/geodis/error_response.py +10 -0
- karrio/schemas/geodis/shipping_request.py +166 -0
- karrio/schemas/geodis/shipping_response.py +91 -0
- karrio/schemas/geodis/tracking_request.py +9 -0
- karrio/schemas/geodis/tracking_response.py +216 -0
- karrio_geodis-2025.5rc1.dist-info/METADATA +45 -0
- karrio_geodis-2025.5rc1.dist-info/RECORD +26 -0
- karrio_geodis-2025.5rc1.dist-info/WHEEL +5 -0
- karrio_geodis-2025.5rc1.dist-info/entry_points.txt +2 -0
- karrio_geodis-2025.5rc1.dist-info/top_level.txt +3 -0
@@ -0,0 +1,51 @@
|
|
1
|
+
"""Karrio GEODIS 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.geodis as provider
|
8
|
+
import karrio.mappers.geodis.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_tracking_request(
|
19
|
+
self, payload: models.TrackingRequest
|
20
|
+
) -> lib.Serializable:
|
21
|
+
return provider.tracking_request(payload, self.settings)
|
22
|
+
|
23
|
+
def create_shipment_request(
|
24
|
+
self, payload: models.ShipmentRequest
|
25
|
+
) -> lib.Serializable:
|
26
|
+
return provider.shipment_request(payload, self.settings)
|
27
|
+
|
28
|
+
def create_cancel_shipment_request(
|
29
|
+
self, payload: models.ShipmentCancelRequest
|
30
|
+
) -> lib.Serializable:
|
31
|
+
return provider.shipment_cancel_request(payload, self.settings)
|
32
|
+
|
33
|
+
def parse_rate_response(
|
34
|
+
self, response: lib.Deserializable
|
35
|
+
) -> typing.Tuple[typing.List[models.RateDetails], typing.List[models.Message]]:
|
36
|
+
return universal_provider.parse_rate_response(response, self.settings)
|
37
|
+
|
38
|
+
def parse_shipment_response(
|
39
|
+
self, response: lib.Deserializable
|
40
|
+
) -> typing.Tuple[models.ShipmentDetails, typing.List[models.Message]]:
|
41
|
+
return provider.parse_shipment_response(response, self.settings)
|
42
|
+
|
43
|
+
def parse_cancel_shipment_response(
|
44
|
+
self, response: lib.Deserializable
|
45
|
+
) -> typing.Tuple[models.ConfirmationDetails, typing.List[models.Message]]:
|
46
|
+
return provider.parse_shipment_cancel_response(response, self.settings)
|
47
|
+
|
48
|
+
def parse_tracking_response(
|
49
|
+
self, response: lib.Deserializable
|
50
|
+
) -> typing.Tuple[typing.List[models.TrackingDetails], typing.List[models.Message]]:
|
51
|
+
return provider.parse_tracking_response(response, self.settings)
|
@@ -0,0 +1,76 @@
|
|
1
|
+
"""Karrio GEODIS client proxy."""
|
2
|
+
|
3
|
+
import json
|
4
|
+
import typing
|
5
|
+
import karrio.lib as lib
|
6
|
+
import karrio.api.proxy as proxy
|
7
|
+
import karrio.mappers.geodis.settings as provider_settings
|
8
|
+
import karrio.universal.mappers.rating_proxy as rating_proxy
|
9
|
+
|
10
|
+
|
11
|
+
class Proxy(rating_proxy.RatingMixinProxy, proxy.Proxy):
|
12
|
+
settings: provider_settings.Settings
|
13
|
+
|
14
|
+
def get_rates(self, request: lib.Serializable) -> lib.Deserializable[str]:
|
15
|
+
return super().get_rates(request)
|
16
|
+
|
17
|
+
def create_shipment(self, request: lib.Serializable) -> lib.Deserializable[str]:
|
18
|
+
service = "api/wsclient/enregistrement-envois"
|
19
|
+
data = request.serialize()
|
20
|
+
|
21
|
+
response = lib.request(
|
22
|
+
url=f"{self.settings.server_url}/{service}",
|
23
|
+
data=json.dumps(data, separators=(",", ":")),
|
24
|
+
trace=self.trace_as("json"),
|
25
|
+
method="POST",
|
26
|
+
headers={
|
27
|
+
"Accept": "*/*",
|
28
|
+
"Content-Type": "application/json",
|
29
|
+
"X-GEODIS-Service": self.settings.get_token(service, data),
|
30
|
+
},
|
31
|
+
)
|
32
|
+
|
33
|
+
return lib.Deserializable(response, lib.to_dict, request.ctx)
|
34
|
+
|
35
|
+
def cancel_shipment(self, request: lib.Serializable) -> lib.Deserializable[str]:
|
36
|
+
service = "api/wsclient/suppression-envois"
|
37
|
+
data = request.serialize()
|
38
|
+
|
39
|
+
response = lib.request(
|
40
|
+
url=f"{self.settings.server_url}/{service}",
|
41
|
+
data=json.dumps(data, separators=(",", ":")),
|
42
|
+
trace=self.trace_as("json"),
|
43
|
+
method="POST",
|
44
|
+
headers={
|
45
|
+
"Accept": "*/*",
|
46
|
+
"Content-Type": "application/json",
|
47
|
+
"X-GEODIS-Service": self.settings.get_token(service, data),
|
48
|
+
},
|
49
|
+
)
|
50
|
+
|
51
|
+
return lib.Deserializable(response, lib.to_dict)
|
52
|
+
|
53
|
+
def get_tracking(self, requests: lib.Serializable) -> lib.Deserializable:
|
54
|
+
service = "api/zoomclient/recherche-envoi"
|
55
|
+
track = lambda data: (
|
56
|
+
data["noSuivi"],
|
57
|
+
lib.request(
|
58
|
+
url=f"{self.settings.server_url}/{service}",
|
59
|
+
trace=self.trace_as("json"),
|
60
|
+
method="POST",
|
61
|
+
data=json.dumps(data, separators=(",", ":")),
|
62
|
+
headers={
|
63
|
+
"Content-Type": "application/json",
|
64
|
+
"X-GEODIS-Service": self.settings.get_token(service, data),
|
65
|
+
},
|
66
|
+
),
|
67
|
+
)
|
68
|
+
|
69
|
+
responses: typing.List[typing.Tuple[str, str]] = lib.run_asynchronously(
|
70
|
+
track, requests.serialize()
|
71
|
+
)
|
72
|
+
|
73
|
+
return lib.Deserializable(
|
74
|
+
responses,
|
75
|
+
lambda response: [(key, lib.to_dict(res)) for key, res in response],
|
76
|
+
)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
"""Karrio GEODIS client settings."""
|
2
|
+
|
3
|
+
import attr
|
4
|
+
import typing
|
5
|
+
import jstruct
|
6
|
+
import karrio.core.models as models
|
7
|
+
import karrio.providers.geodis.utils as provider_utils
|
8
|
+
import karrio.providers.geodis.units as provider_units
|
9
|
+
|
10
|
+
|
11
|
+
@attr.s(auto_attribs=True)
|
12
|
+
class Settings(provider_utils.Settings):
|
13
|
+
"""GEODIS connection settings."""
|
14
|
+
|
15
|
+
# required carrier specific properties
|
16
|
+
api_key: str
|
17
|
+
identifier: str
|
18
|
+
code_client: str = None
|
19
|
+
language: provider_utils.LanguageEnum = "fr" # type: ignore
|
20
|
+
|
21
|
+
# generic properties
|
22
|
+
id: str = None
|
23
|
+
test_mode: bool = False
|
24
|
+
carrier_id: str = "geodis"
|
25
|
+
account_country_code: str = "FR"
|
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.geodis as mappers
|
3
|
+
import karrio.providers.geodis.units as units
|
4
|
+
|
5
|
+
|
6
|
+
METADATA = metadata.PluginMetadata(
|
7
|
+
status="beta",
|
8
|
+
id="geodis",
|
9
|
+
label="GEODIS",
|
10
|
+
# Integrations
|
11
|
+
Mapper=mappers.Mapper,
|
12
|
+
Proxy=mappers.Proxy,
|
13
|
+
Settings=mappers.Settings,
|
14
|
+
# Data Units
|
15
|
+
is_hub=False,
|
16
|
+
options=units.ShippingOption,
|
17
|
+
services=units.ShippingService,
|
18
|
+
connection_configs=units.ConnectionConfig,
|
19
|
+
service_levels=units.DEFAULT_SERVICES,
|
20
|
+
)
|
@@ -0,0 +1,11 @@
|
|
1
|
+
from karrio.providers.geodis.utils import Settings
|
2
|
+
from karrio.providers.geodis.shipment import (
|
3
|
+
parse_shipment_cancel_response,
|
4
|
+
parse_shipment_response,
|
5
|
+
shipment_cancel_request,
|
6
|
+
shipment_request,
|
7
|
+
)
|
8
|
+
from karrio.providers.geodis.tracking import (
|
9
|
+
parse_tracking_response,
|
10
|
+
tracking_request,
|
11
|
+
)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
import karrio.schemas.geodis.error_response as geodis
|
2
|
+
import typing
|
3
|
+
import karrio.lib as lib
|
4
|
+
import karrio.core.models as models
|
5
|
+
import karrio.providers.geodis.utils as provider_utils
|
6
|
+
|
7
|
+
|
8
|
+
def parse_error_response(
|
9
|
+
response: typing.Union[dict, typing.List[dict]],
|
10
|
+
settings: provider_utils.Settings,
|
11
|
+
**kwargs,
|
12
|
+
) -> typing.List[models.Message]:
|
13
|
+
responses = response if isinstance(response, list) else [response]
|
14
|
+
errors = [
|
15
|
+
lib.to_object(geodis.ErrorResponseType, res)
|
16
|
+
for res in responses
|
17
|
+
if res.get("ok") is False
|
18
|
+
]
|
19
|
+
|
20
|
+
return [
|
21
|
+
models.Message(
|
22
|
+
carrier_id=settings.carrier_id,
|
23
|
+
carrier_name=settings.carrier_name,
|
24
|
+
code=error.codeErreur,
|
25
|
+
message=error.texteErreur,
|
26
|
+
details={**kwargs},
|
27
|
+
)
|
28
|
+
for error in errors
|
29
|
+
]
|
@@ -0,0 +1,39 @@
|
|
1
|
+
import karrio.schemas.geodis.cancel_request as geodis
|
2
|
+
import typing
|
3
|
+
import karrio.lib as lib
|
4
|
+
import karrio.core.models as models
|
5
|
+
import karrio.providers.geodis.error as error
|
6
|
+
import karrio.providers.geodis.utils as provider_utils
|
7
|
+
import karrio.providers.geodis.units as provider_units
|
8
|
+
|
9
|
+
|
10
|
+
def parse_shipment_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
|
+
|
16
|
+
messages = error.parse_error_response(response, settings)
|
17
|
+
success = response.get("ok") is True
|
18
|
+
|
19
|
+
confirmation = (
|
20
|
+
models.ConfirmationDetails(
|
21
|
+
carrier_id=settings.carrier_id,
|
22
|
+
carrier_name=settings.carrier_name,
|
23
|
+
operation="Cancel Shipment",
|
24
|
+
success=success,
|
25
|
+
)
|
26
|
+
if success
|
27
|
+
else None
|
28
|
+
)
|
29
|
+
|
30
|
+
return confirmation, messages
|
31
|
+
|
32
|
+
|
33
|
+
def shipment_cancel_request(
|
34
|
+
payload: models.ShipmentCancelRequest,
|
35
|
+
settings: provider_utils.Settings,
|
36
|
+
) -> lib.Serializable:
|
37
|
+
request = geodis.CancelRequestType(listNosSuivis=[payload.shipment_identifier])
|
38
|
+
|
39
|
+
return lib.Serializable(request, lib.to_dict)
|
@@ -0,0 +1,202 @@
|
|
1
|
+
import karrio.schemas.geodis.shipping_request as geodis
|
2
|
+
import karrio.schemas.geodis.shipping_response as shipping
|
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.geodis.error as error
|
8
|
+
import karrio.providers.geodis.utils as provider_utils
|
9
|
+
import karrio.providers.geodis.units as provider_units
|
10
|
+
|
11
|
+
|
12
|
+
def parse_shipment_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
|
+
|
18
|
+
messages = (
|
19
|
+
error.parse_error_response(response, settings)
|
20
|
+
if response.get("ok") is False
|
21
|
+
else []
|
22
|
+
)
|
23
|
+
shipment = (
|
24
|
+
_extract_details(response, settings, _response.ctx)
|
25
|
+
if response.get("ok")
|
26
|
+
else None
|
27
|
+
)
|
28
|
+
|
29
|
+
return shipment, messages
|
30
|
+
|
31
|
+
|
32
|
+
def _extract_details(
|
33
|
+
data: dict,
|
34
|
+
settings: provider_utils.Settings,
|
35
|
+
ctx: dict,
|
36
|
+
) -> models.ShipmentDetails:
|
37
|
+
shipment = lib.to_object(
|
38
|
+
shipping.ShippingResponseType, data
|
39
|
+
).contenu.listRetoursEnvois[0]
|
40
|
+
label = shipment.docEtiquette.contenu
|
41
|
+
|
42
|
+
return models.ShipmentDetails(
|
43
|
+
carrier_id=settings.carrier_id,
|
44
|
+
carrier_name=settings.carrier_name,
|
45
|
+
tracking_number=shipment.noSuivi,
|
46
|
+
shipment_identifier=shipment.noSuivi,
|
47
|
+
label_type=ctx.get("label_type", "PDF"),
|
48
|
+
docs=models.Documents(label=label),
|
49
|
+
meta=dict(
|
50
|
+
carrier_tracking_link=shipment.urlSuiviDestinataire,
|
51
|
+
noRecepisse=shipment.noRecepisse,
|
52
|
+
codeProduit=shipment.codeProduit,
|
53
|
+
),
|
54
|
+
)
|
55
|
+
|
56
|
+
|
57
|
+
def shipment_request(
|
58
|
+
payload: models.ShipmentRequest,
|
59
|
+
settings: provider_utils.Settings,
|
60
|
+
) -> lib.Serializable:
|
61
|
+
shipper = lib.to_address(payload.shipper)
|
62
|
+
recipient = lib.to_address(payload.recipient)
|
63
|
+
packages = lib.to_packages(payload.parcels)
|
64
|
+
service = provider_units.ShippingService.map(payload.service).value_or_key
|
65
|
+
customs = lib.to_customs_info(payload.customs)
|
66
|
+
options = lib.to_shipping_options(
|
67
|
+
payload.options,
|
68
|
+
package_options=packages.options,
|
69
|
+
option_type=provider_units.ShippingOption,
|
70
|
+
)
|
71
|
+
label_type = provider_units.LabelType.map(payload.label_type or "PDF")
|
72
|
+
|
73
|
+
request = geodis.ShippingRequestType(
|
74
|
+
modificationParReference1=None,
|
75
|
+
impressionEtiquette=True,
|
76
|
+
typeImpressionEtiquette=label_type.value or "P",
|
77
|
+
formatEtiquette="1",
|
78
|
+
validationEnvoi=options.geodis_validate_envoi.state,
|
79
|
+
suppressionSiEchecValidation=True,
|
80
|
+
impressionBordereau=False,
|
81
|
+
impressionRecapitulatif=True,
|
82
|
+
listEnvois=[
|
83
|
+
geodis.ListEnvoisType(
|
84
|
+
noRecepisse=options.geodis_no_recepisse.state,
|
85
|
+
noSuivi=None,
|
86
|
+
horsSite=None,
|
87
|
+
codeSa=settings.connection_config.agency_code.state,
|
88
|
+
codeClient=settings.code_client,
|
89
|
+
codeProduit=service,
|
90
|
+
reference1=payload.reference,
|
91
|
+
reference2=None,
|
92
|
+
expediteur=geodis.DestinataireType(
|
93
|
+
nom=shipper.company_name or shipper.person_name,
|
94
|
+
adresse1=shipper.address_line1,
|
95
|
+
adresse2=shipper.address_line2,
|
96
|
+
codePostal=shipper.postal_code,
|
97
|
+
ville=shipper.city,
|
98
|
+
codePays=shipper.country_code,
|
99
|
+
nomContact=shipper.person_name,
|
100
|
+
email=shipper.email,
|
101
|
+
telFixe=shipper.phone_number,
|
102
|
+
indTelMobile=None,
|
103
|
+
telMobile=None,
|
104
|
+
codePorte=shipper.suite,
|
105
|
+
codeTiers=None,
|
106
|
+
noEntrepositaireAgree=None,
|
107
|
+
particulier=shipper.residential,
|
108
|
+
),
|
109
|
+
dateDepartEnlevement=lib.fdate(options.shipment_date.state),
|
110
|
+
instructionEnlevement=options.geodis_instruction_enlevement.state,
|
111
|
+
destinataire=geodis.DestinataireType(
|
112
|
+
nom=recipient.company_name or recipient.person_name,
|
113
|
+
adresse1=recipient.address_line1,
|
114
|
+
adresse2=recipient.address_line2,
|
115
|
+
codePostal=recipient.postal_code,
|
116
|
+
ville=recipient.city,
|
117
|
+
codePays=recipient.country_code,
|
118
|
+
nomContact=recipient.person_name,
|
119
|
+
email=recipient.email,
|
120
|
+
telFixe=recipient.phone_number,
|
121
|
+
indTelMobile=None,
|
122
|
+
telMobile=None,
|
123
|
+
codePorte=recipient.suite,
|
124
|
+
codeTiers=None,
|
125
|
+
noEntrepositaireAgree=None,
|
126
|
+
particulier=recipient.residential,
|
127
|
+
),
|
128
|
+
listUmgs=[
|
129
|
+
geodis.ListUmgType(
|
130
|
+
palette=(
|
131
|
+
package.packaging_type == units.PackagingUnit.pallet.name
|
132
|
+
),
|
133
|
+
paletteConsignee=None,
|
134
|
+
quantite=1,
|
135
|
+
poids=package.weight.KG,
|
136
|
+
volume=package.volume.m3,
|
137
|
+
longueurUnitaire=package.length.CM,
|
138
|
+
largeurUnitaire=package.width.CM,
|
139
|
+
hauteurUnitaire=package.height.CM,
|
140
|
+
referenceColis=package.parcel.reference_number,
|
141
|
+
)
|
142
|
+
for package in packages
|
143
|
+
],
|
144
|
+
natureEnvoi=None,
|
145
|
+
poidsTotal=packages.weight.KG,
|
146
|
+
volumeTotal=packages.volume.m3,
|
147
|
+
largerTotal=None,
|
148
|
+
hauteurTotal=None,
|
149
|
+
longueurTotal=None,
|
150
|
+
uniteTaxation=None,
|
151
|
+
animauxPlumes=None,
|
152
|
+
optionLivraison=next(
|
153
|
+
(
|
154
|
+
option.code
|
155
|
+
for _, option in options.items()
|
156
|
+
if option.state is True
|
157
|
+
),
|
158
|
+
None,
|
159
|
+
),
|
160
|
+
codeSaBureauRestant=None,
|
161
|
+
idPointRelais=None,
|
162
|
+
dateLivraison=options.geodis_date_livraison.state,
|
163
|
+
heureLivraison=options.geodis_heure_livraison.state,
|
164
|
+
instructionLivraison=options.geodis_instruction_livraison.state,
|
165
|
+
natureMarchandise=None,
|
166
|
+
valeurDeclaree=None,
|
167
|
+
contreRemboursement=None,
|
168
|
+
codeIncotermConditionLivraison=(
|
169
|
+
provider_units.Incoterm.map(customs.incoterm).value or "P"
|
170
|
+
),
|
171
|
+
typeTva=None,
|
172
|
+
sadLivToph=None,
|
173
|
+
sadSwap=None,
|
174
|
+
sadLivEtage=None,
|
175
|
+
sadMiseLieuUtil=None,
|
176
|
+
sadDepotage=None,
|
177
|
+
etage=None,
|
178
|
+
emailNotificationDestinataire=(
|
179
|
+
options.email_notification_to.state or recipient.email
|
180
|
+
),
|
181
|
+
smsNotificationDestinataire=shipper.phone_number,
|
182
|
+
emailNotificationExpediteur=shipper.email,
|
183
|
+
emailConfirmationEnlevement=None,
|
184
|
+
emailPriseEnChargeEnlevement=None,
|
185
|
+
poidsQteLimiteeMD=None,
|
186
|
+
dangerEnvQteLimiteeMD=None,
|
187
|
+
nbColisQteExcepteeMD=None,
|
188
|
+
dangerEnvQteExcepteeMD=None,
|
189
|
+
listMatieresDangereuses=[],
|
190
|
+
listVinsSpiritueux=None,
|
191
|
+
nosUmsAEtiqueter=None,
|
192
|
+
listDocumentsEnvoi=[],
|
193
|
+
informationDouane=None,
|
194
|
+
)
|
195
|
+
],
|
196
|
+
)
|
197
|
+
|
198
|
+
return lib.Serializable(
|
199
|
+
request,
|
200
|
+
lib.to_dict,
|
201
|
+
dict(label_type=label_type.name or "PDF"),
|
202
|
+
)
|
@@ -0,0 +1,96 @@
|
|
1
|
+
import karrio.schemas.geodis.tracking_request as geodis
|
2
|
+
import karrio.schemas.geodis.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.geodis.error as error
|
8
|
+
import karrio.providers.geodis.utils as provider_utils
|
9
|
+
import karrio.providers.geodis.units as provider_units
|
10
|
+
|
11
|
+
|
12
|
+
def parse_tracking_response(
|
13
|
+
_responses: lib.Deserializable[typing.List[typing.Tuple[str, dict]]],
|
14
|
+
settings: provider_utils.Settings,
|
15
|
+
) -> typing.Tuple[typing.List[models.TrackingDetails], typing.List[models.Message]]:
|
16
|
+
responses = _responses.deserialize()
|
17
|
+
|
18
|
+
messages: typing.List[models.Message] = sum(
|
19
|
+
[
|
20
|
+
error.parse_error_response(response, settings, tracking_number=_)
|
21
|
+
for _, response in responses
|
22
|
+
],
|
23
|
+
start=[],
|
24
|
+
)
|
25
|
+
tracking_details = [
|
26
|
+
_extract_details(details, settings)
|
27
|
+
for _, details in responses
|
28
|
+
if details.get("ok") is True
|
29
|
+
]
|
30
|
+
|
31
|
+
return tracking_details, messages
|
32
|
+
|
33
|
+
|
34
|
+
def _extract_details(
|
35
|
+
data: dict,
|
36
|
+
settings: provider_utils.Settings,
|
37
|
+
) -> models.TrackingDetails:
|
38
|
+
contenu = lib.to_object(tracking.TrackingResponseType, data).contenu
|
39
|
+
delivered = any(contenu.libelleLivraison or "")
|
40
|
+
status = (
|
41
|
+
units.TrackingStatus.delivered.name
|
42
|
+
if delivered
|
43
|
+
else units.TrackingStatus.in_transit.name
|
44
|
+
)
|
45
|
+
|
46
|
+
return models.TrackingDetails(
|
47
|
+
carrier_id=settings.carrier_id,
|
48
|
+
carrier_name=settings.carrier_name,
|
49
|
+
tracking_number=contenu.noSuivi,
|
50
|
+
events=[
|
51
|
+
models.TrackingEvent(
|
52
|
+
date=lib.fdate(event.dateSuivi),
|
53
|
+
description=event.libelleSuivi,
|
54
|
+
code=event.codeSituationJustification,
|
55
|
+
time=lib.flocaltime(event.heureSuivi),
|
56
|
+
location=event.libelleCentre,
|
57
|
+
)
|
58
|
+
for event in contenu.listSuivis
|
59
|
+
],
|
60
|
+
estimated_delivery=lib.fdate(contenu.dateLivraisonPrevue),
|
61
|
+
status=status,
|
62
|
+
delivered=delivered,
|
63
|
+
info=models.TrackingInfo(
|
64
|
+
carrier_tracking_link=contenu.urlSuiviDestinataire,
|
65
|
+
shipment_service=contenu.prestationCommerciale.libelle,
|
66
|
+
expected_delivery=lib.fdate(contenu.dateLivraisonPrevue),
|
67
|
+
shipment_package_count=contenu.nbColis,
|
68
|
+
package_weight=contenu.poids,
|
69
|
+
customer_name=contenu.destinataire.nom,
|
70
|
+
shipment_origin_country=contenu.expediteur.pays.libelle,
|
71
|
+
shipment_origin_postal_code=contenu.expediteur.codePostal,
|
72
|
+
shipment_destination_country=contenu.destinataire.pays.libelle,
|
73
|
+
shipment_destination_postal_code=contenu.destinataire.codePostal,
|
74
|
+
shipping_date=lib.fdate(contenu.dateDepart),
|
75
|
+
),
|
76
|
+
meta=dict(
|
77
|
+
reference1=contenu.reference1,
|
78
|
+
reference2=contenu.reference2,
|
79
|
+
refEdides=contenu.refEdides,
|
80
|
+
refUniExp=contenu.refUniExp,
|
81
|
+
codeClient=contenu.codeClient,
|
82
|
+
noRecepisse=contenu.noRecepisse,
|
83
|
+
),
|
84
|
+
)
|
85
|
+
|
86
|
+
|
87
|
+
def tracking_request(
|
88
|
+
payload: models.TrackingRequest,
|
89
|
+
settings: provider_utils.Settings,
|
90
|
+
) -> lib.Serializable:
|
91
|
+
request = [
|
92
|
+
geodis.TrackingRequestType(noSuivi=tracking_number)
|
93
|
+
for tracking_number in payload.tracking_numbers
|
94
|
+
]
|
95
|
+
|
96
|
+
return lib.Serializable(request, lib.to_dict)
|