karrio-colissimo 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/colissimo/__init__.py +3 -0
- karrio/mappers/colissimo/mapper.py +41 -0
- karrio/mappers/colissimo/proxy.py +39 -0
- karrio/mappers/colissimo/settings.py +35 -0
- karrio/plugins/colissimo/__init__.py +23 -0
- karrio/providers/colissimo/__init__.py +9 -0
- karrio/providers/colissimo/error.py +52 -0
- karrio/providers/colissimo/shipment/__init__.py +4 -0
- karrio/providers/colissimo/shipment/create.py +295 -0
- karrio/providers/colissimo/tracking.py +79 -0
- karrio/providers/colissimo/units.py +169 -0
- karrio/providers/colissimo/utils.py +71 -0
- karrio/schemas/colissimo/__init__.py +0 -0
- karrio/schemas/colissimo/error_response.py +13 -0
- karrio/schemas/colissimo/label_request.py +182 -0
- karrio/schemas/colissimo/label_response.py +26 -0
- karrio/schemas/colissimo/tracking_request.py +7 -0
- karrio/schemas/colissimo/tracking_response.py +61 -0
- karrio_colissimo-2025.5rc1.dist-info/METADATA +45 -0
- karrio_colissimo-2025.5rc1.dist-info/RECORD +23 -0
- karrio_colissimo-2025.5rc1.dist-info/WHEEL +5 -0
- karrio_colissimo-2025.5rc1.dist-info/entry_points.txt +2 -0
- karrio_colissimo-2025.5rc1.dist-info/top_level.txt +3 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
"""Karrio Colissimo 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.colissimo as provider
|
8
|
+
import karrio.mappers.colissimo.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 parse_rate_response(
|
29
|
+
self, response: lib.Deserializable[str]
|
30
|
+
) -> typing.Tuple[typing.List[models.RateDetails], typing.List[models.Message]]:
|
31
|
+
return provider.parse_rate_response(response, self.settings)
|
32
|
+
|
33
|
+
def parse_shipment_response(
|
34
|
+
self, response: lib.Deserializable[str]
|
35
|
+
) -> typing.Tuple[models.ShipmentDetails, typing.List[models.Message]]:
|
36
|
+
return provider.parse_shipment_response(response, self.settings)
|
37
|
+
|
38
|
+
def parse_tracking_response(
|
39
|
+
self, response: lib.Deserializable[str]
|
40
|
+
) -> typing.Tuple[typing.List[models.TrackingDetails], typing.List[models.Message]]:
|
41
|
+
return provider.parse_tracking_response(response, self.settings)
|
@@ -0,0 +1,39 @@
|
|
1
|
+
"""Karrio Colissimo client proxy."""
|
2
|
+
|
3
|
+
import karrio.lib as lib
|
4
|
+
import karrio.api.proxy as proxy
|
5
|
+
import karrio.providers.colissimo.utils as provider_utils
|
6
|
+
import karrio.mappers.colissimo.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}/generateLabel",
|
19
|
+
data=request.serialize(),
|
20
|
+
trace=self.trace_as("json"),
|
21
|
+
method="POST",
|
22
|
+
headers={"Content-Type": "application/json;charset=UTF-8"},
|
23
|
+
)
|
24
|
+
|
25
|
+
return lib.Deserializable(response, provider_utils.parse_response, request.ctx)
|
26
|
+
|
27
|
+
def get_tracking(self, request: lib.Serializable) -> lib.Deserializable[str]:
|
28
|
+
idships = ",".join(request.serialize())
|
29
|
+
response = lib.request(
|
30
|
+
url=f"{self.settings.laposte_server_url}/idships/{idships}?lang={self.settings.connection_config.lang.state or 'fr_FR'}",
|
31
|
+
trace=self.trace_as("json"),
|
32
|
+
method="GET",
|
33
|
+
headers={
|
34
|
+
"accept": "application/json",
|
35
|
+
"X-Okapi-Key": self.settings.laposte_api_key,
|
36
|
+
},
|
37
|
+
)
|
38
|
+
|
39
|
+
return lib.Deserializable(response, lib.to_dict)
|
@@ -0,0 +1,35 @@
|
|
1
|
+
"""Karrio Colissimo client settings."""
|
2
|
+
|
3
|
+
import attr
|
4
|
+
import typing
|
5
|
+
import jstruct
|
6
|
+
import karrio.core.models as models
|
7
|
+
import karrio.providers.colissimo.utils as provider_utils
|
8
|
+
import karrio.providers.colissimo.units as provider_units
|
9
|
+
|
10
|
+
|
11
|
+
@attr.s(auto_attribs=True)
|
12
|
+
class Settings(provider_utils.Settings):
|
13
|
+
"""Colissimo connection settings."""
|
14
|
+
|
15
|
+
# required carrier specific properties
|
16
|
+
password: str
|
17
|
+
contract_number: str
|
18
|
+
laposte_api_key: str = None
|
19
|
+
|
20
|
+
# generic properties
|
21
|
+
id: str = None
|
22
|
+
test_mode: bool = False
|
23
|
+
carrier_id: str = "colissimo"
|
24
|
+
account_country_code: str = "FR"
|
25
|
+
metadata: dict = {}
|
26
|
+
config: dict = {}
|
27
|
+
|
28
|
+
services: typing.List[models.ServiceLevel] = jstruct.JList[models.ServiceLevel, False, dict(default=provider_units.DEFAULT_SERVICES)] # type: ignore
|
29
|
+
|
30
|
+
@property
|
31
|
+
def shipping_services(self) -> typing.List[models.ServiceLevel]:
|
32
|
+
if any(self.services or []):
|
33
|
+
return self.services
|
34
|
+
|
35
|
+
return provider_units.DEFAULT_SERVICES
|
@@ -0,0 +1,23 @@
|
|
1
|
+
import karrio.core.metadata as metadata
|
2
|
+
import karrio.mappers.colissimo as mappers
|
3
|
+
import karrio.providers.colissimo.units as units
|
4
|
+
|
5
|
+
|
6
|
+
METADATA = metadata.PluginMetadata(
|
7
|
+
status="beta",
|
8
|
+
id="colissimo",
|
9
|
+
label="Colissimo",
|
10
|
+
# Integrations
|
11
|
+
Mapper=mappers.Mapper,
|
12
|
+
Proxy=mappers.Proxy,
|
13
|
+
Settings=mappers.Settings,
|
14
|
+
# Data Units
|
15
|
+
options=units.ShippingOption,
|
16
|
+
services=units.ShippingService,
|
17
|
+
connection_configs=units.ConnectionConfig,
|
18
|
+
service_levels=units.DEFAULT_SERVICES,
|
19
|
+
# New fields
|
20
|
+
website="https://www.colissimo.entreprise.laposte.fr/en",
|
21
|
+
documentation="https://www.colissimo.entreprise.laposte.fr/en/tools-and-services",
|
22
|
+
description="Envoi de colis en France et dans le monde entier, livraison à domicile ou en point de retrait, Colissimo vous offre un choix de services qui facilitent votre quotidien.",
|
23
|
+
)
|
@@ -0,0 +1,52 @@
|
|
1
|
+
import karrio.schemas.colissimo.error_response as laposte
|
2
|
+
import typing
|
3
|
+
import karrio.lib as lib
|
4
|
+
import karrio.core.models as models
|
5
|
+
import karrio.providers.colissimo.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
|
+
messages = response.get("json_info", {}).get("messages", [])
|
14
|
+
|
15
|
+
return [
|
16
|
+
models.Message(
|
17
|
+
carrier_id=settings.carrier_id,
|
18
|
+
carrier_name=settings.carrier_name,
|
19
|
+
code=msg.get("type"),
|
20
|
+
message=msg.get("messageContent"),
|
21
|
+
details={**kwargs},
|
22
|
+
)
|
23
|
+
for msg in messages
|
24
|
+
if msg.get("type") == "ERROR"
|
25
|
+
]
|
26
|
+
|
27
|
+
|
28
|
+
def parse_laposte_error_response(
|
29
|
+
response: typing.Union[dict, typing.List[dict]],
|
30
|
+
settings: provider_utils.Settings,
|
31
|
+
**kwargs,
|
32
|
+
) -> typing.List[models.Message]:
|
33
|
+
responses = response if isinstance(response, list) else [response]
|
34
|
+
errors = [
|
35
|
+
lib.to_object(laposte.ErrorResponse, res)
|
36
|
+
for res in responses
|
37
|
+
if (
|
38
|
+
not str(res.get("returnCode")).startswith("20")
|
39
|
+
or res.get("code") is not None
|
40
|
+
)
|
41
|
+
]
|
42
|
+
|
43
|
+
return [
|
44
|
+
models.Message(
|
45
|
+
carrier_id=settings.carrier_id,
|
46
|
+
carrier_name=settings.carrier_name,
|
47
|
+
code=(error.returnCode or error.code),
|
48
|
+
message=(error.returnMessage or error.message),
|
49
|
+
details={**kwargs},
|
50
|
+
)
|
51
|
+
for error in errors
|
52
|
+
]
|
@@ -0,0 +1,295 @@
|
|
1
|
+
import karrio.schemas.colissimo.label_request as colissimo
|
2
|
+
import karrio.schemas.colissimo.label_response as shipping
|
3
|
+
import typing
|
4
|
+
import base64
|
5
|
+
import karrio.lib as lib
|
6
|
+
import karrio.core.units as units
|
7
|
+
import karrio.core.models as models
|
8
|
+
import karrio.providers.colissimo.error as error
|
9
|
+
import karrio.providers.colissimo.utils as provider_utils
|
10
|
+
import karrio.providers.colissimo.units as provider_units
|
11
|
+
|
12
|
+
|
13
|
+
def parse_shipment_response(
|
14
|
+
_response: lib.Deserializable[dict],
|
15
|
+
settings: provider_utils.Settings,
|
16
|
+
) -> typing.Tuple[typing.List[models.RateDetails], typing.List[models.Message]]:
|
17
|
+
response = _response.deserialize()
|
18
|
+
|
19
|
+
messages = error.parse_error_response(response, settings)
|
20
|
+
shipment = (
|
21
|
+
_extract_details(response, settings, _response.ctx)
|
22
|
+
if response.get("json_info", {}).get("labelV2Response") is not None
|
23
|
+
else None
|
24
|
+
)
|
25
|
+
|
26
|
+
return shipment, messages
|
27
|
+
|
28
|
+
|
29
|
+
def _extract_details(
|
30
|
+
data: dict,
|
31
|
+
settings: provider_utils.Settings,
|
32
|
+
ctx: dict = {},
|
33
|
+
) -> models.ShipmentDetails:
|
34
|
+
shipment = lib.to_object(shipping.LabelResponse, data.get("json_info"))
|
35
|
+
label_type = ctx.get("label_type") or "PDF"
|
36
|
+
label = data.get("label")
|
37
|
+
|
38
|
+
if label_type != "ZPL":
|
39
|
+
label = base64.b64encode(bytes(label, encoding="raw_unicode_escape")).decode(
|
40
|
+
"utf-8"
|
41
|
+
)
|
42
|
+
|
43
|
+
return models.ShipmentDetails(
|
44
|
+
carrier_id=settings.carrier_id,
|
45
|
+
carrier_name=settings.carrier_name,
|
46
|
+
tracking_number=shipment.labelV2Response.parcelNumber,
|
47
|
+
shipment_identifier=shipment.labelV2Response.parcelNumber,
|
48
|
+
label_type="ZPL" if "ZPL" in label_type else "PDF",
|
49
|
+
docs=models.Documents(label=label),
|
50
|
+
meta=dict(
|
51
|
+
carrier_tracking_link=settings.tracking_url.format(
|
52
|
+
shipment.labelV2Response.parcelNumber
|
53
|
+
),
|
54
|
+
request_uuid=data.get("uuid"),
|
55
|
+
pdfUrl=shipment.labelV2Response.pdfUrl,
|
56
|
+
parcelNumber=shipment.labelV2Response.parcelNumber,
|
57
|
+
parcelNumberPartner=shipment.labelV2Response.parcelNumberPartner,
|
58
|
+
),
|
59
|
+
)
|
60
|
+
|
61
|
+
|
62
|
+
def shipment_request(
|
63
|
+
payload: models.ShipmentRequest,
|
64
|
+
settings: provider_utils.Settings,
|
65
|
+
) -> lib.Serializable:
|
66
|
+
shipper = lib.to_address(payload.shipper)
|
67
|
+
recipient = lib.to_address(payload.recipient)
|
68
|
+
package = lib.to_packages(payload.parcels).single
|
69
|
+
service = provider_units.ShippingService.map(payload.service).value_or_key
|
70
|
+
options = lib.to_shipping_options(
|
71
|
+
payload.options,
|
72
|
+
package_options=package.options,
|
73
|
+
option_type=provider_units.ShippingOption,
|
74
|
+
)
|
75
|
+
customs = lib.to_customs_info(
|
76
|
+
payload.customs,
|
77
|
+
option_type=provider_units.ShippingOption,
|
78
|
+
shipper=shipper,
|
79
|
+
recipient=recipient,
|
80
|
+
)
|
81
|
+
|
82
|
+
request = colissimo.LabelRequest(
|
83
|
+
contractNumber=settings.contract_number,
|
84
|
+
password=settings.password,
|
85
|
+
outputFormat=colissimo.OutputFormat(
|
86
|
+
x=0,
|
87
|
+
y=0,
|
88
|
+
outputPrintingType=(
|
89
|
+
provider_units.LabelType.map(payload.label_type).value
|
90
|
+
or provider_utils.LabelType.PDF.value
|
91
|
+
),
|
92
|
+
dematerialized=None,
|
93
|
+
returnType=None,
|
94
|
+
printCODDocument=None,
|
95
|
+
),
|
96
|
+
letter=colissimo.Letter(
|
97
|
+
service=colissimo.Service(
|
98
|
+
productCode=service,
|
99
|
+
depositDate=lib.fdate(options.shipment_date.state, "%Y-%m-%d"),
|
100
|
+
mailBoxPicking=None,
|
101
|
+
mailBoxPickingDate=None,
|
102
|
+
vatCode=None,
|
103
|
+
vatPercentage=None,
|
104
|
+
vatAmount=None,
|
105
|
+
transportationAmount=options.declared_value.state,
|
106
|
+
totalAmount=options.declared_value.state,
|
107
|
+
orderNumber=None,
|
108
|
+
commercialName=shipper.company_name,
|
109
|
+
returnTypeChoice=None,
|
110
|
+
reseauPostal=0,
|
111
|
+
),
|
112
|
+
parcel=colissimo.Parcel(
|
113
|
+
parcelNumber=package.parcel.reference_number,
|
114
|
+
insuranceAmount=None,
|
115
|
+
insuranceValue=options.insurance.state,
|
116
|
+
recommendationLevel=None,
|
117
|
+
weight=package.weight.KG,
|
118
|
+
nonMachinable=options.colissimo_non_machinable.state,
|
119
|
+
returnReceipt=options.colissimo_retun_receipt.state,
|
120
|
+
instructions=None,
|
121
|
+
pickupLocationId=None,
|
122
|
+
ftd=options.colissimo_ftd.state,
|
123
|
+
ddp=options.colissimo_ddp.state,
|
124
|
+
codamount=options.cash_on_delivery.state,
|
125
|
+
codcurrency=options.currency.state,
|
126
|
+
cod=options.cash_on_delivery.state is not None,
|
127
|
+
),
|
128
|
+
customsDeclarations=(
|
129
|
+
colissimo.CustomsDeclarations(
|
130
|
+
includeCustomsDeclarations=True,
|
131
|
+
numberOfCopies=None,
|
132
|
+
contents=colissimo.Contents(
|
133
|
+
article=[
|
134
|
+
colissimo.Article(
|
135
|
+
description=item.description,
|
136
|
+
quantity=item.quantity,
|
137
|
+
weight=item.weight,
|
138
|
+
value=item.value_amount,
|
139
|
+
hsCode=item.hs_code,
|
140
|
+
originCountry=item.origin_country,
|
141
|
+
originCountryLabel=None,
|
142
|
+
currency=options.currency.state,
|
143
|
+
artref=item.metadata.get("artref", None),
|
144
|
+
originalIdent=None,
|
145
|
+
vatAmount=None,
|
146
|
+
customsFees=item.metadata.get("customs_fees", None),
|
147
|
+
)
|
148
|
+
for item in customs.commodities
|
149
|
+
],
|
150
|
+
category=None,
|
151
|
+
original=None,
|
152
|
+
explanations=None,
|
153
|
+
),
|
154
|
+
importersReference=None,
|
155
|
+
importersContact=shipper.contact,
|
156
|
+
officeOrigin=None,
|
157
|
+
comments=None,
|
158
|
+
description=customs.content_description,
|
159
|
+
invoiceNumber=customs.invoice,
|
160
|
+
licenceNumber=customs.options.license_number.state,
|
161
|
+
certificatNumber=customs.options.certificate_number.state,
|
162
|
+
importerAddress=colissimo.Address(
|
163
|
+
companyName=customs.duty_billing_address.company_name,
|
164
|
+
lastName=customs.duty_billing_address.person_name,
|
165
|
+
firstName=None,
|
166
|
+
line0=customs.duty_billing_address.suite,
|
167
|
+
line1=customs.duty_billing_address.street_number,
|
168
|
+
line2=customs.duty_billing_address.address_line1,
|
169
|
+
line3=customs.duty_billing_address.address_line2,
|
170
|
+
countryCode=customs.duty_billing_address.country_code,
|
171
|
+
countryLabel=customs.duty_billing_address.country_name,
|
172
|
+
city=customs.duty_billing_address.city,
|
173
|
+
zipCode=customs.duty_billing_address.postal_code,
|
174
|
+
phoneNumber=None,
|
175
|
+
mobileNumber=customs.duty_billing_address.phone_number,
|
176
|
+
doorCode1=None,
|
177
|
+
doorCode2=None,
|
178
|
+
intercom=None,
|
179
|
+
email=customs.duty_billing_address.email,
|
180
|
+
language=None,
|
181
|
+
stateOrProvinceCode=customs.duty_billing_address.state_code,
|
182
|
+
),
|
183
|
+
)
|
184
|
+
if payload.customs is not None
|
185
|
+
else None
|
186
|
+
),
|
187
|
+
sender=colissimo.Sender(
|
188
|
+
senderParcelRef=payload.reference or package.parcel.reference_number,
|
189
|
+
address=colissimo.Address(
|
190
|
+
companyName=shipper.company_name,
|
191
|
+
lastName=shipper.person_name,
|
192
|
+
firstName=None,
|
193
|
+
line0=shipper.suite,
|
194
|
+
line1=shipper.street_number,
|
195
|
+
line2=shipper.address_line1,
|
196
|
+
line3=shipper.address_line2,
|
197
|
+
countryCode=shipper.country_code,
|
198
|
+
countryLabel=shipper.country_name,
|
199
|
+
city=shipper.city,
|
200
|
+
zipCode=shipper.postal_code,
|
201
|
+
phoneNumber=shipper.phone_number,
|
202
|
+
mobileNumber=None,
|
203
|
+
doorCode1=None,
|
204
|
+
doorCode2=None,
|
205
|
+
intercom=None,
|
206
|
+
email=shipper.email,
|
207
|
+
language="FR",
|
208
|
+
stateOrProvinceCode=shipper.state_code,
|
209
|
+
),
|
210
|
+
),
|
211
|
+
addressee=colissimo.Addressee(
|
212
|
+
addresseeParcelRef=payload.reference or package.parcel.reference_number,
|
213
|
+
codeBarForReference=None,
|
214
|
+
serviceInfo=None,
|
215
|
+
promotionCode=None,
|
216
|
+
address=colissimo.Address(
|
217
|
+
companyName=recipient.company_name,
|
218
|
+
lastName=recipient.person_name,
|
219
|
+
firstName=None,
|
220
|
+
line0=recipient.suite,
|
221
|
+
line1=recipient.street_number,
|
222
|
+
line2=recipient.address_line1,
|
223
|
+
line3=recipient.address_line2,
|
224
|
+
countryCode=recipient.country_code,
|
225
|
+
countryLabel=recipient.country_name,
|
226
|
+
city=recipient.city,
|
227
|
+
zipCode=recipient.postal_code,
|
228
|
+
phoneNumber=recipient.phone_number,
|
229
|
+
mobileNumber=None,
|
230
|
+
doorCode1=None,
|
231
|
+
doorCode2=None,
|
232
|
+
intercom=None,
|
233
|
+
email=recipient.email,
|
234
|
+
language="FR",
|
235
|
+
stateOrProvinceCode=recipient.state_code,
|
236
|
+
),
|
237
|
+
),
|
238
|
+
codSenderAddress=(
|
239
|
+
colissimo.Address(
|
240
|
+
companyName=recipient.company_name,
|
241
|
+
lastName=recipient.person_name,
|
242
|
+
firstName=None,
|
243
|
+
line0=recipient.suite,
|
244
|
+
line1=recipient.street_number,
|
245
|
+
line2=recipient.address_line1,
|
246
|
+
line3=recipient.address_line2,
|
247
|
+
countryCode=recipient.country_code,
|
248
|
+
countryLabel=recipient.country_name,
|
249
|
+
city=recipient.city,
|
250
|
+
zipCode=recipient.postal_code,
|
251
|
+
phoneNumber=recipient.phone_number,
|
252
|
+
mobileNumber=None,
|
253
|
+
doorCode1=None,
|
254
|
+
doorCode2=None,
|
255
|
+
intercom=None,
|
256
|
+
email=recipient.email,
|
257
|
+
language="FR",
|
258
|
+
stateOrProvinceCode=recipient.state_code,
|
259
|
+
)
|
260
|
+
if options.cash_on_delivery.state is not None
|
261
|
+
else None
|
262
|
+
),
|
263
|
+
uploadDocument=None,
|
264
|
+
features=colissimo.Features(printTrackingBarcode=True),
|
265
|
+
),
|
266
|
+
fields=(
|
267
|
+
colissimo.Fields(
|
268
|
+
customField=[
|
269
|
+
colissimo.Field(
|
270
|
+
key=key,
|
271
|
+
value=value,
|
272
|
+
)
|
273
|
+
for key, value in [
|
274
|
+
("LENGTH", package.length.value),
|
275
|
+
("WIDTH", package.width.value),
|
276
|
+
("HEIGHT", package.height.value),
|
277
|
+
]
|
278
|
+
]
|
279
|
+
)
|
280
|
+
if any(
|
281
|
+
[
|
282
|
+
package.length.value,
|
283
|
+
package.width.value,
|
284
|
+
package.height.value,
|
285
|
+
]
|
286
|
+
)
|
287
|
+
else None
|
288
|
+
),
|
289
|
+
)
|
290
|
+
|
291
|
+
return lib.Serializable(
|
292
|
+
request,
|
293
|
+
lib.to_dict,
|
294
|
+
dict(label_type=payload.label_type or "PDF"),
|
295
|
+
)
|
@@ -0,0 +1,79 @@
|
|
1
|
+
import karrio.schemas.colissimo.tracking_response as colissimo
|
2
|
+
import typing
|
3
|
+
import karrio.lib as lib
|
4
|
+
import karrio.core.units as units
|
5
|
+
import karrio.core.models as models
|
6
|
+
import karrio.providers.colissimo.error as error
|
7
|
+
import karrio.providers.colissimo.utils as provider_utils
|
8
|
+
import karrio.providers.colissimo.units as provider_units
|
9
|
+
|
10
|
+
|
11
|
+
def parse_tracking_response(
|
12
|
+
_response: lib.Deserializable[typing.Union[dict, typing.List[dict]]],
|
13
|
+
settings: provider_utils.Settings,
|
14
|
+
) -> typing.Tuple[typing.List[models.TrackingDetails], typing.List[models.Message]]:
|
15
|
+
response = _response.deserialize()
|
16
|
+
|
17
|
+
responses = response if isinstance(response, list) else [response]
|
18
|
+
messages = error.parse_laposte_error_response(responses, settings)
|
19
|
+
tracking_details = [
|
20
|
+
_extract_details(res["shipment"], settings)
|
21
|
+
for res in responses
|
22
|
+
if str(res.get("returnCode")).startswith("20")
|
23
|
+
]
|
24
|
+
|
25
|
+
return tracking_details, messages
|
26
|
+
|
27
|
+
|
28
|
+
def _extract_details(
|
29
|
+
data: dict,
|
30
|
+
settings: provider_utils.Settings,
|
31
|
+
) -> models.TrackingDetails:
|
32
|
+
shipment = lib.to_object(colissimo.Shipment, data)
|
33
|
+
status = next(
|
34
|
+
(
|
35
|
+
status.name
|
36
|
+
for status in list(provider_units.TrackingStatus)
|
37
|
+
if shipment.event[0].code in status.value
|
38
|
+
),
|
39
|
+
provider_units.TrackingStatus.in_transit.name,
|
40
|
+
)
|
41
|
+
|
42
|
+
return models.TrackingDetails(
|
43
|
+
carrier_id=settings.carrier_id,
|
44
|
+
carrier_name=settings.carrier_name,
|
45
|
+
tracking_number=shipment.idShip,
|
46
|
+
status=status,
|
47
|
+
events=[
|
48
|
+
models.TrackingEvent(
|
49
|
+
date=lib.fdate(event.date, "%Y-%m-%dT%H:%M:%S%z"),
|
50
|
+
description=event.label,
|
51
|
+
code=event.code,
|
52
|
+
time=lib.flocaltime(event.date, "%Y-%m-%dT%H:%M:%S%z"),
|
53
|
+
)
|
54
|
+
for event in shipment.event
|
55
|
+
],
|
56
|
+
estimated_delivery=lib.fdate(shipment.deliveryDate, "%Y-%m-%dT%H:%M:%S%z"),
|
57
|
+
delivered=shipment.isFinal,
|
58
|
+
info=models.TrackingInfo(
|
59
|
+
carrier_tracking_link=shipment.url,
|
60
|
+
expected_delivery=lib.fdate(shipment.estimDate, "%Y-%m-%dT%H:%M:%S%z"),
|
61
|
+
shipment_service=shipment.product,
|
62
|
+
shipping_date=lib.fdate(shipment.entryDate, "%Y-%m-%dT%H:%M:%S%z"),
|
63
|
+
shipment_origin_country=getattr(
|
64
|
+
shipment.contextData, "originCountry", None
|
65
|
+
),
|
66
|
+
shipment_destination_country=getattr(
|
67
|
+
shipment.contextData, "arrivalCountry", None
|
68
|
+
),
|
69
|
+
),
|
70
|
+
)
|
71
|
+
|
72
|
+
|
73
|
+
def tracking_request(
|
74
|
+
payload: models.TrackingRequest,
|
75
|
+
settings: provider_utils.Settings,
|
76
|
+
) -> lib.Serializable:
|
77
|
+
request = payload.tracking_numbers
|
78
|
+
|
79
|
+
return lib.Serializable(request)
|
@@ -0,0 +1,169 @@
|
|
1
|
+
import karrio.lib as lib
|
2
|
+
import karrio.core.units as units
|
3
|
+
import karrio.core.models as models
|
4
|
+
|
5
|
+
|
6
|
+
class PackagingType(lib.StrEnum):
|
7
|
+
"""Carrier specific packaging type"""
|
8
|
+
|
9
|
+
PACKAGE = "PACKAGE"
|
10
|
+
|
11
|
+
""" Unified Packaging type mapping """
|
12
|
+
envelope = PACKAGE
|
13
|
+
pak = PACKAGE
|
14
|
+
tube = PACKAGE
|
15
|
+
pallet = PACKAGE
|
16
|
+
small_box = PACKAGE
|
17
|
+
medium_box = PACKAGE
|
18
|
+
your_packaging = PACKAGE
|
19
|
+
|
20
|
+
|
21
|
+
class LabelType(lib.Enum):
|
22
|
+
ZPL_10x15_203dpi = "ZPL_10x15_203dpi"
|
23
|
+
ZPL_10x15_300dpi = "ZPL_10x15_300dpi"
|
24
|
+
DPL_10x15_203dpi = "DPL_10x15_203dpi"
|
25
|
+
DPL_10x15_300dpi = "DPL_10x15_300dpi"
|
26
|
+
PDF_10x15_300dpi = "PDF_10x15_300dpi"
|
27
|
+
PDF_A4_300dpi = "PDF_A4_300dpi"
|
28
|
+
ZPL_10x10_203dpi = "ZPL_10x10_203dpi"
|
29
|
+
ZPL_10x10_300dpi = "ZPL_10x10_300dpi"
|
30
|
+
DPL_10x10_203dpi = "DPL_10x10_203dpi"
|
31
|
+
DPL_10x10_300dpi = "DPL_10x10_300dpi"
|
32
|
+
PDF_10x10_300dpi = "PDF_10x10_300dpi"
|
33
|
+
PDF_10x12_300dpi = "PDF_10x12_300dpi"
|
34
|
+
ZPL_10x15_203dpi_UL = "ZPL_10x15_203dpi_UL"
|
35
|
+
ZPL_10x15_300dpi_UL = "ZPL_10x15_300dpi_UL"
|
36
|
+
DPL_10x15_203dpi_UL = "DPL_10x15_203dpi_UL"
|
37
|
+
DPL_10x15_300dpi_UL = "DPL_10x15_300dpi_UL"
|
38
|
+
PDF_10x15_300dpi_UL = "PDF_10x15_300dpi_UL"
|
39
|
+
PDF_A4_300dpi_UL = "PDF_A4_300dpi_UL"
|
40
|
+
|
41
|
+
""" Unified Label type mapping """
|
42
|
+
PDF = PDF_10x15_300dpi
|
43
|
+
ZPL = ZPL_10x10_300dpi
|
44
|
+
|
45
|
+
|
46
|
+
class ConnectionConfig(lib.Enum):
|
47
|
+
lang = lib.OptionEnum("lang", lib.units.create_enum("Lang", ["FR", "EN"]))
|
48
|
+
|
49
|
+
|
50
|
+
class ServiceName(lib.Enum):
|
51
|
+
"""Carrier specific services"""
|
52
|
+
|
53
|
+
colissimo_home_without_signature = "Colissimo Home - without signature"
|
54
|
+
colissimo_home_with_signature = "Colissimo Home - with signature"
|
55
|
+
colissimo_eco_france = "Colissimo Eco France"
|
56
|
+
colissimo_return_france = "Colissimo Return France CORE 8R***"
|
57
|
+
colissimo_flash_without_signature = "Colissimo Flash – without signature"
|
58
|
+
colissimo_flash_with_signature = "Colissimo Flash – with signature"
|
59
|
+
colissimo_oversea_home_without_signature = "Colissimo Home OM - without signature"
|
60
|
+
colissimo_oversea_home_with_signature = "Colissimo Home OM - with signature"
|
61
|
+
colissimo_eco_om_without_signature = "Colissimo Eco OM - without signature"
|
62
|
+
colissimo_eco_om_with_signature = "Colissimo Eco OM - with signature"
|
63
|
+
colissimo_retour_om = "Colissimo Retour OM"
|
64
|
+
colissimo_home_international_without_signature = (
|
65
|
+
"Colissimo Home International - without signature***"
|
66
|
+
)
|
67
|
+
colissimo_home_international_with_signature = (
|
68
|
+
"Colissimo Home International - with signature***"
|
69
|
+
)
|
70
|
+
colissimo_return_international_to_france = (
|
71
|
+
"Colissimo Return International – Foreign country to France"
|
72
|
+
)
|
73
|
+
colissimo_return_international_from_france = (
|
74
|
+
"Colissimo Return International – France to foreign cournty"
|
75
|
+
)
|
76
|
+
colissimo_economical_big_export_offer = (
|
77
|
+
"Economical Big Export offer (test offer for China for a pilot customer)"
|
78
|
+
)
|
79
|
+
colissimo_out_of_home_national_international = (
|
80
|
+
"Colissimo Out Of Home National and International : **"
|
81
|
+
)
|
82
|
+
colissimo_out_of_home_post_office = "Colissimo - Out Of Home – at Post Office"
|
83
|
+
colissimo_out_of_home_pickup_points_station_lockers = (
|
84
|
+
"Colissimo - Out Of Home – at Pickup points or Pickup Station lockers"
|
85
|
+
)
|
86
|
+
colissimo_out_of_home_pickup_point = "Colissimo - Out Of Home – at pickup point"
|
87
|
+
colissimo_out_of_home_pickup_station_lockers = (
|
88
|
+
"Colissimo - Out Of Home – at Pickup Station lockers"
|
89
|
+
)
|
90
|
+
|
91
|
+
|
92
|
+
class ShippingService(lib.StrEnum):
|
93
|
+
"""Carrier specific services"""
|
94
|
+
|
95
|
+
colissimo_home_without_signature = "DOM"
|
96
|
+
colissimo_home_with_signature = "DOS"
|
97
|
+
colissimo_eco_france = "CECO"
|
98
|
+
colissimo_return_france = "CORE"
|
99
|
+
colissimo_flash_without_signature = "COLR"
|
100
|
+
colissimo_flash_with_signature = "J+1"
|
101
|
+
colissimo_oversea_home_without_signature = "COM"
|
102
|
+
colissimo_oversea_home_with_signature = "CDS"
|
103
|
+
colissimo_eco_om_without_signature = "ECO"
|
104
|
+
colissimo_eco_om_with_signature = "ECOS"
|
105
|
+
colissimo_retour_om = "CORI"
|
106
|
+
colissimo_home_international_without_signature = colissimo_home_without_signature
|
107
|
+
colissimo_home_international_with_signature = colissimo_home_with_signature
|
108
|
+
colissimo_return_international_to_france = colissimo_retour_om
|
109
|
+
colissimo_return_international_from_france = "CORF"
|
110
|
+
colissimo_economical_big_export_offer = "ACCI"
|
111
|
+
colissimo_out_of_home_national_international = "HD"
|
112
|
+
colissimo_out_of_home_post_office = colissimo_out_of_home_national_international
|
113
|
+
colissimo_out_of_home_pickup_points_station_lockers = (
|
114
|
+
colissimo_out_of_home_national_international
|
115
|
+
)
|
116
|
+
colissimo_out_of_home_pickup_point = colissimo_out_of_home_national_international
|
117
|
+
colissimo_out_of_home_pickup_station_lockers = (
|
118
|
+
colissimo_out_of_home_national_international
|
119
|
+
)
|
120
|
+
|
121
|
+
|
122
|
+
class ShippingOption(lib.Enum):
|
123
|
+
"""Carrier specific options"""
|
124
|
+
|
125
|
+
colissimo_insurance_value = lib.OptionEnum("insuranceValue", lib.to_money)
|
126
|
+
colissimo_cod_amount = lib.OptionEnum("CODAmount", lib.to_money)
|
127
|
+
colissimo_return_receipt = lib.OptionEnum("returnReceipt", bool)
|
128
|
+
colissimo_ftd = lib.OptionEnum("ftd", bool)
|
129
|
+
colissimo_non_machinable = lib.OptionEnum("nonMachinable", bool)
|
130
|
+
colissimo_ddp = lib.OptionEnum("ddp", bool)
|
131
|
+
colissimo_instructions = lib.OptionEnum("instructions")
|
132
|
+
|
133
|
+
""" Unified Option type mapping """
|
134
|
+
insurance = colissimo_insurance_value
|
135
|
+
cash_on_delivery = colissimo_cod_amount
|
136
|
+
|
137
|
+
|
138
|
+
def shipping_options_initializer(
|
139
|
+
options: dict,
|
140
|
+
package_options: units.ShippingOptions = None,
|
141
|
+
) -> units.ShippingOptions:
|
142
|
+
"""
|
143
|
+
Apply default values to the given options.
|
144
|
+
"""
|
145
|
+
|
146
|
+
if package_options is not None:
|
147
|
+
options.update(package_options.content)
|
148
|
+
|
149
|
+
def items_filter(key: str) -> bool:
|
150
|
+
return key in ShippingOption # type: ignore
|
151
|
+
|
152
|
+
return units.ShippingOptions(options, ShippingOption, items_filter=items_filter)
|
153
|
+
|
154
|
+
|
155
|
+
class TrackingStatus(lib.Enum):
|
156
|
+
delivered = ["DI1"]
|
157
|
+
in_transit = [""]
|
158
|
+
out_for_delivery = ["MD2", "ET1"]
|
159
|
+
|
160
|
+
|
161
|
+
DEFAULT_SERVICES = [
|
162
|
+
models.ServiceLevel(
|
163
|
+
service_name="Colissimo Home - without signature",
|
164
|
+
service_code="colissimo_home_without_signature",
|
165
|
+
currency="EUR",
|
166
|
+
domicile=True,
|
167
|
+
zones=[models.ServiceZone(label="Zone 1", rate=0.0)],
|
168
|
+
),
|
169
|
+
]
|
@@ -0,0 +1,71 @@
|
|
1
|
+
import karrio.lib as lib
|
2
|
+
import karrio.core as core
|
3
|
+
|
4
|
+
JSON_START = """<jsonInfos>
|
5
|
+
|
6
|
+
{"""
|
7
|
+
JSON_END = """}
|
8
|
+
--uuid:"""
|
9
|
+
LABEL_START = """<label>
|
10
|
+
|
11
|
+
"""
|
12
|
+
LABEL_END = r"""
|
13
|
+
--uuid:"""
|
14
|
+
|
15
|
+
|
16
|
+
class Settings(core.Settings):
|
17
|
+
"""Colissimo connection settings."""
|
18
|
+
|
19
|
+
password: str
|
20
|
+
contract_number: str
|
21
|
+
laposte_api_key: str = None
|
22
|
+
|
23
|
+
account_country_code: str = "FR"
|
24
|
+
config: dict = {}
|
25
|
+
|
26
|
+
@property
|
27
|
+
def carrier_name(self):
|
28
|
+
return "colissimo"
|
29
|
+
|
30
|
+
@property
|
31
|
+
def server_url(self):
|
32
|
+
return "https://ws.colissimo.fr/sls-ws/SlsServiceWSRest/2.0"
|
33
|
+
|
34
|
+
@property
|
35
|
+
def laposte_server_url(self):
|
36
|
+
return "https://api.laposte.fr/suivi/v2"
|
37
|
+
|
38
|
+
@property
|
39
|
+
def tracking_url(self):
|
40
|
+
return "https://www.laposte.fr/outils/suivre-vos-envois?code={}"
|
41
|
+
|
42
|
+
|
43
|
+
def parse_response(response: str) -> dict:
|
44
|
+
"""Parse colissimo multipart response."""
|
45
|
+
|
46
|
+
uuid = lib.failsafe(
|
47
|
+
lambda: response[
|
48
|
+
response.rfind("--uuid:") + len("--uuid:") : response.rfind("--")
|
49
|
+
]
|
50
|
+
)
|
51
|
+
json_info = lib.failsafe(
|
52
|
+
lambda: response[
|
53
|
+
response.find(JSON_START) + len(JSON_START) : response.rfind(JSON_END)
|
54
|
+
]
|
55
|
+
)
|
56
|
+
label = lib.failsafe(
|
57
|
+
lambda: (
|
58
|
+
response[
|
59
|
+
response.find(LABEL_START)
|
60
|
+
+ len(LABEL_START) : response.rfind(LABEL_END)
|
61
|
+
]
|
62
|
+
if "<label>" in response
|
63
|
+
else None
|
64
|
+
)
|
65
|
+
)
|
66
|
+
|
67
|
+
return dict(
|
68
|
+
uuid=uuid,
|
69
|
+
label=label,
|
70
|
+
json_info=lib.to_dict("{" + (json_info or "") + "}"),
|
71
|
+
)
|
File without changes
|
@@ -0,0 +1,13 @@
|
|
1
|
+
from attr import s
|
2
|
+
from typing import Optional
|
3
|
+
|
4
|
+
|
5
|
+
@s(auto_attribs=True)
|
6
|
+
class ErrorResponse:
|
7
|
+
returnCode: Optional[int] = None
|
8
|
+
returnMessage: Optional[str] = None
|
9
|
+
lang: Optional[str] = None
|
10
|
+
scope: Optional[str] = None
|
11
|
+
idShip: Optional[str] = None
|
12
|
+
code: Optional[str] = None
|
13
|
+
message: Optional[str] = None
|
@@ -0,0 +1,182 @@
|
|
1
|
+
from attr import s
|
2
|
+
from typing import Optional, List
|
3
|
+
from jstruct import JList, JStruct
|
4
|
+
|
5
|
+
|
6
|
+
@s(auto_attribs=True)
|
7
|
+
class Field:
|
8
|
+
key: Optional[str] = None
|
9
|
+
value: Optional[str] = None
|
10
|
+
|
11
|
+
|
12
|
+
@s(auto_attribs=True)
|
13
|
+
class Fields:
|
14
|
+
field: List[Field] = JList[Field]
|
15
|
+
customField: List[Field] = JList[Field]
|
16
|
+
|
17
|
+
|
18
|
+
@s(auto_attribs=True)
|
19
|
+
class Address:
|
20
|
+
companyName: Optional[str] = None
|
21
|
+
lastName: Optional[str] = None
|
22
|
+
firstName: Optional[str] = None
|
23
|
+
line0: Optional[str] = None
|
24
|
+
line1: Optional[str] = None
|
25
|
+
line2: Optional[str] = None
|
26
|
+
line3: Optional[str] = None
|
27
|
+
countryCode: Optional[str] = None
|
28
|
+
countryLabel: Optional[str] = None
|
29
|
+
city: Optional[str] = None
|
30
|
+
zipCode: Optional[str] = None
|
31
|
+
phoneNumber: Optional[str] = None
|
32
|
+
mobileNumber: Optional[str] = None
|
33
|
+
doorCode1: Optional[str] = None
|
34
|
+
doorCode2: Optional[str] = None
|
35
|
+
intercom: Optional[str] = None
|
36
|
+
email: Optional[str] = None
|
37
|
+
language: Optional[str] = None
|
38
|
+
stateOrProvinceCode: Optional[str] = None
|
39
|
+
|
40
|
+
|
41
|
+
@s(auto_attribs=True)
|
42
|
+
class Addressee:
|
43
|
+
addresseeParcelRef: Optional[str] = None
|
44
|
+
codeBarForReference: Optional[bool] = None
|
45
|
+
serviceInfo: Optional[str] = None
|
46
|
+
promotionCode: Optional[str] = None
|
47
|
+
address: Optional[Address] = JStruct[Address]
|
48
|
+
|
49
|
+
|
50
|
+
@s(auto_attribs=True)
|
51
|
+
class Article:
|
52
|
+
description: Optional[str] = None
|
53
|
+
quantity: Optional[int] = None
|
54
|
+
weight: Optional[int] = None
|
55
|
+
value: Optional[int] = None
|
56
|
+
hsCode: Optional[str] = None
|
57
|
+
originCountry: Optional[str] = None
|
58
|
+
originCountryLabel: Optional[str] = None
|
59
|
+
currency: Optional[str] = None
|
60
|
+
artref: Optional[str] = None
|
61
|
+
originalIdent: Optional[str] = None
|
62
|
+
vatAmount: Optional[int] = None
|
63
|
+
customsFees: Optional[int] = None
|
64
|
+
|
65
|
+
|
66
|
+
@s(auto_attribs=True)
|
67
|
+
class Category:
|
68
|
+
value: Optional[int] = None
|
69
|
+
|
70
|
+
|
71
|
+
@s(auto_attribs=True)
|
72
|
+
class Original:
|
73
|
+
originalIdent: Optional[str] = None
|
74
|
+
originalInvoiceNumber: Optional[str] = None
|
75
|
+
originalInvoiceDate: Optional[str] = None
|
76
|
+
originalParcelNumber: Optional[str] = None
|
77
|
+
|
78
|
+
|
79
|
+
@s(auto_attribs=True)
|
80
|
+
class Contents:
|
81
|
+
article: List[Article] = JList[Article]
|
82
|
+
category: Optional[Category] = JStruct[Category]
|
83
|
+
original: List[Original] = JList[Original]
|
84
|
+
explanations: Optional[str] = None
|
85
|
+
|
86
|
+
|
87
|
+
@s(auto_attribs=True)
|
88
|
+
class CustomsDeclarations:
|
89
|
+
includeCustomsDeclarations: Optional[bool] = None
|
90
|
+
numberOfCopies: Optional[int] = None
|
91
|
+
contents: Optional[Contents] = JStruct[Contents]
|
92
|
+
importersReference: Optional[str] = None
|
93
|
+
importersContact: Optional[str] = None
|
94
|
+
officeOrigin: Optional[str] = None
|
95
|
+
comments: Optional[str] = None
|
96
|
+
description: Optional[str] = None
|
97
|
+
invoiceNumber: Optional[str] = None
|
98
|
+
licenceNumber: Optional[str] = None
|
99
|
+
certificatNumber: Optional[str] = None
|
100
|
+
importerAddress: Optional[Address] = JStruct[Address]
|
101
|
+
|
102
|
+
|
103
|
+
@s(auto_attribs=True)
|
104
|
+
class Features:
|
105
|
+
printTrackingBarcode: Optional[bool] = None
|
106
|
+
|
107
|
+
|
108
|
+
@s(auto_attribs=True)
|
109
|
+
class Parcel:
|
110
|
+
parcelNumber: Optional[str] = None
|
111
|
+
insuranceAmount: Optional[int] = None
|
112
|
+
insuranceValue: Optional[int] = None
|
113
|
+
recommendationLevel: Optional[str] = None
|
114
|
+
weight: Optional[int] = None
|
115
|
+
nonMachinable: Optional[bool] = None
|
116
|
+
returnReceipt: Optional[bool] = None
|
117
|
+
instructions: Optional[str] = None
|
118
|
+
pickupLocationId: Optional[str] = None
|
119
|
+
ftd: Optional[bool] = None
|
120
|
+
ddp: Optional[bool] = None
|
121
|
+
codamount: Optional[int] = None
|
122
|
+
codcurrency: Optional[str] = None
|
123
|
+
cod: Optional[bool] = None
|
124
|
+
|
125
|
+
|
126
|
+
@s(auto_attribs=True)
|
127
|
+
class Sender:
|
128
|
+
senderParcelRef: Optional[str] = None
|
129
|
+
address: Optional[Address] = JStruct[Address]
|
130
|
+
|
131
|
+
|
132
|
+
@s(auto_attribs=True)
|
133
|
+
class Service:
|
134
|
+
productCode: Optional[str] = None
|
135
|
+
depositDate: Optional[str] = None
|
136
|
+
mailBoxPicking: Optional[bool] = None
|
137
|
+
mailBoxPickingDate: Optional[str] = None
|
138
|
+
vatCode: Optional[int] = None
|
139
|
+
vatPercentage: Optional[int] = None
|
140
|
+
vatAmount: Optional[int] = None
|
141
|
+
transportationAmount: Optional[int] = None
|
142
|
+
totalAmount: Optional[int] = None
|
143
|
+
orderNumber: Optional[str] = None
|
144
|
+
commercialName: Optional[str] = None
|
145
|
+
returnTypeChoice: Optional[int] = None
|
146
|
+
reseauPostal: Optional[str] = None
|
147
|
+
|
148
|
+
|
149
|
+
@s(auto_attribs=True)
|
150
|
+
class UploadDocument:
|
151
|
+
documentContent: List[str] = []
|
152
|
+
|
153
|
+
|
154
|
+
@s(auto_attribs=True)
|
155
|
+
class Letter:
|
156
|
+
service: Optional[Service] = JStruct[Service]
|
157
|
+
parcel: Optional[Parcel] = JStruct[Parcel]
|
158
|
+
customsDeclarations: Optional[CustomsDeclarations] = JStruct[CustomsDeclarations]
|
159
|
+
sender: Optional[Sender] = JStruct[Sender]
|
160
|
+
addressee: Optional[Addressee] = JStruct[Addressee]
|
161
|
+
codSenderAddress: Optional[Address] = JStruct[Address]
|
162
|
+
uploadDocument: Optional[UploadDocument] = JStruct[UploadDocument]
|
163
|
+
features: Optional[Features] = JStruct[Features]
|
164
|
+
|
165
|
+
|
166
|
+
@s(auto_attribs=True)
|
167
|
+
class OutputFormat:
|
168
|
+
x: Optional[int] = None
|
169
|
+
y: Optional[int] = None
|
170
|
+
outputPrintingType: Optional[str] = None
|
171
|
+
dematerialized: Optional[bool] = None
|
172
|
+
returnType: Optional[str] = None
|
173
|
+
printCODDocument: Optional[bool] = None
|
174
|
+
|
175
|
+
|
176
|
+
@s(auto_attribs=True)
|
177
|
+
class LabelRequest:
|
178
|
+
contractNumber: Optional[str] = None
|
179
|
+
password: Optional[str] = None
|
180
|
+
outputFormat: Optional[OutputFormat] = JStruct[OutputFormat]
|
181
|
+
letter: Optional[Letter] = JStruct[Letter]
|
182
|
+
fields: Optional[Fields] = JStruct[Fields]
|
@@ -0,0 +1,26 @@
|
|
1
|
+
from attr import s
|
2
|
+
from typing import Optional, Any, List
|
3
|
+
from jstruct import JList, JStruct
|
4
|
+
|
5
|
+
|
6
|
+
@s(auto_attribs=True)
|
7
|
+
class LabelV2Response:
|
8
|
+
parcelNumber: Optional[str] = None
|
9
|
+
parcelNumberPartner: Optional[str] = None
|
10
|
+
pdfUrl: Any = None
|
11
|
+
fields: Any = None
|
12
|
+
|
13
|
+
|
14
|
+
@s(auto_attribs=True)
|
15
|
+
class Message:
|
16
|
+
id: Optional[int] = None
|
17
|
+
type: Optional[str] = None
|
18
|
+
messageContent: Optional[str] = None
|
19
|
+
replacementValues: List[Any] = []
|
20
|
+
|
21
|
+
|
22
|
+
@s(auto_attribs=True)
|
23
|
+
class LabelResponse:
|
24
|
+
messages: List[Message] = JList[Message]
|
25
|
+
labelXmlV2Reponse: Any = None
|
26
|
+
labelV2Response: Optional[LabelV2Response] = JStruct[LabelV2Response]
|
@@ -0,0 +1,61 @@
|
|
1
|
+
from attr import s
|
2
|
+
from typing import Optional, List
|
3
|
+
from jstruct import JStruct, JList
|
4
|
+
|
5
|
+
|
6
|
+
@s(auto_attribs=True)
|
7
|
+
class DeliveryChoice:
|
8
|
+
deliveryChoice: Optional[int] = None
|
9
|
+
|
10
|
+
|
11
|
+
@s(auto_attribs=True)
|
12
|
+
class ContextData:
|
13
|
+
deliveryChoice: Optional[DeliveryChoice] = JStruct[DeliveryChoice]
|
14
|
+
originCountry: Optional[str] = None
|
15
|
+
arrivalCountry: Optional[str] = None
|
16
|
+
|
17
|
+
|
18
|
+
@s(auto_attribs=True)
|
19
|
+
class Event:
|
20
|
+
code: Optional[str] = None
|
21
|
+
label: Optional[str] = None
|
22
|
+
date: Optional[str] = None
|
23
|
+
|
24
|
+
|
25
|
+
@s(auto_attribs=True)
|
26
|
+
class Timeline:
|
27
|
+
shortLabel: Optional[str] = None
|
28
|
+
longLabel: Optional[str] = None
|
29
|
+
id: Optional[int] = None
|
30
|
+
country: Optional[str] = None
|
31
|
+
status: Optional[bool] = None
|
32
|
+
type: Optional[int] = None
|
33
|
+
date: Optional[str] = None
|
34
|
+
|
35
|
+
|
36
|
+
@s(auto_attribs=True)
|
37
|
+
class Shipment:
|
38
|
+
idShip: Optional[str] = None
|
39
|
+
holder: Optional[int] = None
|
40
|
+
product: Optional[str] = None
|
41
|
+
isFinal: Optional[bool] = None
|
42
|
+
deliveryDate: Optional[str] = None
|
43
|
+
entryDate: Optional[str] = None
|
44
|
+
timeline: List[Timeline] = JList[Timeline]
|
45
|
+
event: List[Event] = JList[Event]
|
46
|
+
contextData: Optional[ContextData] = JStruct[ContextData]
|
47
|
+
estimDate: Optional[str] = None
|
48
|
+
url: Optional[str] = None
|
49
|
+
|
50
|
+
|
51
|
+
@s(auto_attribs=True)
|
52
|
+
class Response:
|
53
|
+
lang: Optional[str] = None
|
54
|
+
scope: Optional[str] = None
|
55
|
+
returnCode: Optional[int] = None
|
56
|
+
shipment: Optional[Shipment] = JStruct[Shipment]
|
57
|
+
|
58
|
+
|
59
|
+
@s(auto_attribs=True)
|
60
|
+
class TrackingResponse:
|
61
|
+
responses: List[Response] = JList[Response]
|
@@ -0,0 +1,45 @@
|
|
1
|
+
Metadata-Version: 2.4
|
2
|
+
Name: karrio_colissimo
|
3
|
+
Version: 2025.5rc1
|
4
|
+
Summary: Karrio - Colissimo Shipping Extension
|
5
|
+
Author-email: karrio <hello@karrio.io>
|
6
|
+
License-Expression: Apache-2.0
|
7
|
+
Project-URL: Homepage, https://github.com/karrioapi/karrio
|
8
|
+
Classifier: Intended Audience :: Developers
|
9
|
+
Classifier: Operating System :: OS Independent
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
11
|
+
Requires-Python: >=3.7
|
12
|
+
Description-Content-Type: text/markdown
|
13
|
+
Requires-Dist: karrio
|
14
|
+
|
15
|
+
|
16
|
+
# karrio.colissimo
|
17
|
+
|
18
|
+
This package is a Colissimo extension of the [karrio](https://pypi.org/project/karrio) multi carrier shipping SDK.
|
19
|
+
|
20
|
+
## Requirements
|
21
|
+
|
22
|
+
`Python 3.7+`
|
23
|
+
|
24
|
+
## Installation
|
25
|
+
|
26
|
+
```bash
|
27
|
+
pip install karrio.colissimo
|
28
|
+
```
|
29
|
+
|
30
|
+
## Usage
|
31
|
+
|
32
|
+
```python
|
33
|
+
import karrio.sdk as karrio
|
34
|
+
from karrio.mappers.colissimo.settings import Settings
|
35
|
+
|
36
|
+
|
37
|
+
# Initialize a carrier gateway
|
38
|
+
colissimo = karrio.gateway["colissimo"].create(
|
39
|
+
Settings(
|
40
|
+
...
|
41
|
+
)
|
42
|
+
)
|
43
|
+
```
|
44
|
+
|
45
|
+
Check the [Karrio Mutli-carrier SDK docs](https://docs.karrio.io) for Shipping API requests
|
@@ -0,0 +1,23 @@
|
|
1
|
+
karrio/mappers/colissimo/__init__.py,sha256=ifjuTREZiGGSrlhTYVKx7UkbRZNqr6m9R_LTA0_jkQ4,155
|
2
|
+
karrio/mappers/colissimo/mapper.py,sha256=-TCZysxQ_67Nz48BFM0qCVCBpkSVRoC1qH-nzbPHHog,1599
|
3
|
+
karrio/mappers/colissimo/proxy.py,sha256=B7jkoqRBBUy3ZIFTjpra40dSqw9O2B9QmzBQm9x6mx8,1532
|
4
|
+
karrio/mappers/colissimo/settings.py,sha256=-NqBwwBDqYWlHoxCRHpIBn3GFwlGgHgtgrDNTN8hd00,1011
|
5
|
+
karrio/plugins/colissimo/__init__.py,sha256=tMZGuJQqNTQe8HULxGBm18Xgd_pjpSbIQUycEWtYktE,868
|
6
|
+
karrio/providers/colissimo/__init__.py,sha256=zGCjtpOeH6IB2BtmFChbuMGFRPcEwxLshRf4AgjPEec,260
|
7
|
+
karrio/providers/colissimo/error.py,sha256=U53tPupLsDcO9Jdbk9niz0PIgCE36hv7LqlfiUJzdwY,1506
|
8
|
+
karrio/providers/colissimo/tracking.py,sha256=4_r5F4jgC8j-be4Sx5RXSGuWbpO36pH_TAcYmUyBn-w,2747
|
9
|
+
karrio/providers/colissimo/units.py,sha256=oBKh9h_87TD3uwQUWNgM8FfDv0KuhSGRnXWFLQZRUPI,6317
|
10
|
+
karrio/providers/colissimo/utils.py,sha256=rWfvBXJ53QS6nSC8FetWZ1SmN3JiwUApvROdwcrZtL4,1555
|
11
|
+
karrio/providers/colissimo/shipment/__init__.py,sha256=wNMIG1QNPaIopEfjD05wLqUjmRhYj4T05kFONkivFzA,110
|
12
|
+
karrio/providers/colissimo/shipment/create.py,sha256=eD0jAD9hHLGy_YCEf3ELoAwq_PZtKumUoSBhciBrDto,12117
|
13
|
+
karrio/schemas/colissimo/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
14
|
+
karrio/schemas/colissimo/error_response.py,sha256=iBYZjvqI6JKwQCfZBObNNfIBG9iUu9Pf-ZgcTicsrd8,330
|
15
|
+
karrio/schemas/colissimo/label_request.py,sha256=pSMOWHrz8ulakt3-HaN86oY6j9bSjIMfla2zQ9sZ1sc,5338
|
16
|
+
karrio/schemas/colissimo/label_response.py,sha256=3g2cwUNTalKVCUmvbpHhGlPdKMIey8eam6xjhfTP9Wo,647
|
17
|
+
karrio/schemas/colissimo/tracking_request.py,sha256=K0S51-ktf4rfXNGKdj-basUAmLALwH8emY_VC_vmpnY,128
|
18
|
+
karrio/schemas/colissimo/tracking_response.py,sha256=U3W2TbdT5ld_ZlZIMXRY62ScCEZ2nsFdcQPTFFNudl0,1525
|
19
|
+
karrio_colissimo-2025.5rc1.dist-info/METADATA,sha256=DOuYP6F130txZtuhVq8jszQ_vE75djHT8MYH9QppqGk,1008
|
20
|
+
karrio_colissimo-2025.5rc1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
21
|
+
karrio_colissimo-2025.5rc1.dist-info/entry_points.txt,sha256=5D8gMo5ptusxiT7anI2epCZNsG5N56UXv83pmZvvvjo,63
|
22
|
+
karrio_colissimo-2025.5rc1.dist-info/top_level.txt,sha256=FZCY8Nwft8oEGHdl--xku8P3TrnOxu5dETEU_fWpRSM,20
|
23
|
+
karrio_colissimo-2025.5rc1.dist-info/RECORD,,
|