karrio-postat 2026.1.3__py3-none-any.whl → 2026.1.5__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/plugins/postat/__init__.py +1 -0
- karrio/providers/postat/error.py +22 -14
- karrio/providers/postat/shipment/cancel.py +12 -12
- karrio/providers/postat/shipment/create.py +62 -57
- karrio/providers/postat/units.py +2 -0
- karrio/providers/postat/utils.py +19 -1
- {karrio_postat-2026.1.3.dist-info → karrio_postat-2026.1.5.dist-info}/METADATA +1 -1
- {karrio_postat-2026.1.3.dist-info → karrio_postat-2026.1.5.dist-info}/RECORD +11 -11
- {karrio_postat-2026.1.3.dist-info → karrio_postat-2026.1.5.dist-info}/WHEEL +0 -0
- {karrio_postat-2026.1.3.dist-info → karrio_postat-2026.1.5.dist-info}/entry_points.txt +0 -0
- {karrio_postat-2026.1.3.dist-info → karrio_postat-2026.1.5.dist-info}/top_level.txt +0 -0
karrio/providers/postat/error.py
CHANGED
|
@@ -13,18 +13,26 @@ def parse_error_response(
|
|
|
13
13
|
**kwargs,
|
|
14
14
|
) -> typing.List[models.Message]:
|
|
15
15
|
"""Parse error response from PostAT SOAP API."""
|
|
16
|
-
|
|
16
|
+
messages: typing.List[models.Message] = []
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
18
|
+
# Extract SOAP faults (standard SOAP error handling)
|
|
19
|
+
messages.extend(extract_fault(response, settings))
|
|
20
|
+
|
|
21
|
+
# Parse PostAT errorMessage element (main error field in responses)
|
|
22
|
+
error_messages = lib.find_element("errorMessage", response) or []
|
|
23
|
+
for err_elem in error_messages:
|
|
24
|
+
if err_elem.text and err_elem.text.strip():
|
|
25
|
+
msg_text = err_elem.text.strip()
|
|
26
|
+
# Avoid duplicates
|
|
27
|
+
if not any(msg_text in (m.message or "") for m in messages):
|
|
28
|
+
messages.append(
|
|
29
|
+
models.Message(
|
|
30
|
+
carrier_id=settings.carrier_id,
|
|
31
|
+
carrier_name=settings.carrier_name,
|
|
32
|
+
code="POSTAT_ERROR",
|
|
33
|
+
message=msg_text,
|
|
34
|
+
details=kwargs if kwargs else None,
|
|
35
|
+
)
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
return messages
|
|
@@ -47,19 +47,19 @@ def shipment_cancel_request(
|
|
|
47
47
|
) -> lib.Serializable:
|
|
48
48
|
"""Create a shipment cancellation request for the PostAT SOAP API."""
|
|
49
49
|
# Build request using generated schema types
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
postat_void.
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
OrgUnitID=settings.org_unit_id,
|
|
57
|
-
OrgUnitGuid=settings.org_unit_guid,
|
|
58
|
-
)
|
|
59
|
-
]
|
|
50
|
+
void_shipment = postat_void.VoidShipmentType(
|
|
51
|
+
row=[
|
|
52
|
+
postat_void.VoidShipmentRowType(
|
|
53
|
+
TrackingNumber=payload.shipment_identifier,
|
|
54
|
+
OrgUnitID=settings.org_unit_id,
|
|
55
|
+
OrgUnitGuid=settings.org_unit_guid,
|
|
60
56
|
)
|
|
61
|
-
|
|
57
|
+
]
|
|
62
58
|
)
|
|
59
|
+
# Set proper element name for PostAT API (VoidShipment, not VoidShipmentType)
|
|
60
|
+
void_shipment.original_tagname_ = "VoidShipment"
|
|
61
|
+
|
|
62
|
+
request = lib.Envelope(Body=lib.Body(void_shipment))
|
|
63
63
|
|
|
64
|
-
return lib.Serializable(request,
|
|
64
|
+
return lib.Serializable(request, provider_utils.standard_request_serializer)
|
|
65
65
|
|
|
@@ -17,9 +17,14 @@ def parse_shipment_response(
|
|
|
17
17
|
response = _response.deserialize()
|
|
18
18
|
messages = error.parse_error_response(response, settings)
|
|
19
19
|
result = lib.find_element("ImportShipmentResult", response, first=True)
|
|
20
|
+
|
|
21
|
+
# Check if we have valid tracking codes before extracting
|
|
22
|
+
code_elements = lib.find_element("Code", result) if result is not None else []
|
|
23
|
+
has_tracking = any(code.text for code in (code_elements or []))
|
|
24
|
+
|
|
20
25
|
shipment = (
|
|
21
26
|
_extract_details(response, settings)
|
|
22
|
-
if result is not None and not any(messages)
|
|
27
|
+
if result is not None and has_tracking and not any(messages)
|
|
23
28
|
else None
|
|
24
29
|
)
|
|
25
30
|
|
|
@@ -86,62 +91,62 @@ def shipment_request(
|
|
|
86
91
|
)
|
|
87
92
|
|
|
88
93
|
# Build request using generated schema types
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
postat.
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
PaperLayoutID=paper_layout,
|
|
140
|
-
),
|
|
141
|
-
)
|
|
142
|
-
]
|
|
94
|
+
import_shipment = postat.ImportShipmentType(
|
|
95
|
+
row=[
|
|
96
|
+
postat.ImportShipmentRowType(
|
|
97
|
+
ClientID=settings.client_id,
|
|
98
|
+
OrgUnitID=settings.org_unit_id,
|
|
99
|
+
OrgUnitGuid=settings.org_unit_guid,
|
|
100
|
+
DeliveryServiceThirdPartyID=service,
|
|
101
|
+
CustomDataBit1=False,
|
|
102
|
+
OUShipperReference1=payload.reference,
|
|
103
|
+
ColloList=postat.ColloListType(
|
|
104
|
+
ColloRow=[
|
|
105
|
+
postat.ColloRowType(
|
|
106
|
+
Weight=package.weight.KG,
|
|
107
|
+
Length=package.length.CM,
|
|
108
|
+
Width=package.width.CM,
|
|
109
|
+
Height=package.height.CM,
|
|
110
|
+
)
|
|
111
|
+
for package in packages
|
|
112
|
+
]
|
|
113
|
+
),
|
|
114
|
+
OURecipientAddress=postat.AddressType(
|
|
115
|
+
Name1=recipient.company_name or recipient.person_name,
|
|
116
|
+
Name2=(
|
|
117
|
+
recipient.person_name
|
|
118
|
+
if recipient.company_name
|
|
119
|
+
else None
|
|
120
|
+
),
|
|
121
|
+
AddressLine1=recipient.street,
|
|
122
|
+
AddressLine2=recipient.address_line2,
|
|
123
|
+
HouseNumber=recipient.street_number,
|
|
124
|
+
PostalCode=recipient.postal_code,
|
|
125
|
+
City=recipient.city,
|
|
126
|
+
CountryID=recipient.country_code,
|
|
127
|
+
Email=recipient.email,
|
|
128
|
+
Tel1=recipient.phone_number,
|
|
129
|
+
),
|
|
130
|
+
OUShipperAddress=postat.AddressType(
|
|
131
|
+
Name1=shipper.company_name or shipper.person_name,
|
|
132
|
+
Name2=shipper.person_name if shipper.company_name else None,
|
|
133
|
+
AddressLine1=shipper.street,
|
|
134
|
+
AddressLine2=shipper.address_line2,
|
|
135
|
+
PostalCode=shipper.postal_code,
|
|
136
|
+
City=shipper.city,
|
|
137
|
+
CountryID=shipper.country_code,
|
|
138
|
+
),
|
|
139
|
+
PrinterObject=postat.PrinterObjectType(
|
|
140
|
+
LabelFormatID=label_size,
|
|
141
|
+
LanguageID=label_format,
|
|
142
|
+
PaperLayoutID=paper_layout,
|
|
143
|
+
),
|
|
143
144
|
)
|
|
144
|
-
|
|
145
|
+
]
|
|
145
146
|
)
|
|
147
|
+
# Set proper element name for PostAT API (ImportShipment, not ImportShipmentType)
|
|
148
|
+
import_shipment.original_tagname_ = "ImportShipment"
|
|
149
|
+
|
|
150
|
+
request = lib.Envelope(Body=lib.Body(import_shipment))
|
|
146
151
|
|
|
147
|
-
return lib.Serializable(request,
|
|
152
|
+
return lib.Serializable(request, provider_utils.standard_request_serializer)
|
karrio/providers/postat/units.py
CHANGED
|
@@ -226,6 +226,8 @@ def load_services_from_csv() -> list:
|
|
|
226
226
|
zone = models.ServiceZone(
|
|
227
227
|
label=row.get("zone_label", "Default Zone"),
|
|
228
228
|
rate=float(row.get("rate", 0.0)),
|
|
229
|
+
min_weight=float(row["min_weight"]) if row.get("min_weight") else None,
|
|
230
|
+
max_weight=float(row["max_weight"]) if row.get("max_weight") else None,
|
|
229
231
|
transit_days=transit_days,
|
|
230
232
|
country_codes=country_codes if country_codes else None,
|
|
231
233
|
)
|
karrio/providers/postat/utils.py
CHANGED
|
@@ -3,6 +3,24 @@
|
|
|
3
3
|
import attr
|
|
4
4
|
import karrio.lib as lib
|
|
5
5
|
import karrio.core as core
|
|
6
|
+
import karrio.core.utils as utils
|
|
7
|
+
from karrio.core.utils.soap import apply_namespaceprefix
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def standard_request_serializer(envelope: lib.Envelope) -> str:
|
|
11
|
+
"""Serialize envelope to PostAT SOAP format with proper namespaces."""
|
|
12
|
+
namespace_def = (
|
|
13
|
+
'xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" '
|
|
14
|
+
'xmlns:post="http://post.ondot.at"'
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
envelope.ns_prefix_ = "soapenv"
|
|
18
|
+
envelope.Body.ns_prefix_ = "soapenv"
|
|
19
|
+
|
|
20
|
+
for node in envelope.Body.anytypeobjs_:
|
|
21
|
+
apply_namespaceprefix(node, "post")
|
|
22
|
+
|
|
23
|
+
return utils.XP.export(envelope, namespacedef_=namespace_def)
|
|
6
24
|
|
|
7
25
|
|
|
8
26
|
@attr.s(auto_attribs=True)
|
|
@@ -35,7 +53,7 @@ class Settings(core.Settings):
|
|
|
35
53
|
"""
|
|
36
54
|
return (
|
|
37
55
|
self.connection_config.server_url.state
|
|
38
|
-
or "https://plc.post.at/Post.Webservice/ShippingService.svc"
|
|
56
|
+
or "https://plc.post.at/Post.Webservice/ShippingService.svc/secure"
|
|
39
57
|
)
|
|
40
58
|
|
|
41
59
|
@property
|
|
@@ -2,19 +2,19 @@ karrio/mappers/postat/__init__.py,sha256=c12wXYUbeqRwfHWCaApOehQEaAn6y58dnzizXn0
|
|
|
2
2
|
karrio/mappers/postat/mapper.py,sha256=meokZ91UDJjuzBfK6u0Wz31lFuoD4K5pVmS9HpY-tz8,1630
|
|
3
3
|
karrio/mappers/postat/proxy.py,sha256=B5pIX2Q-uQJhZjZlJtNIwxbn51p_7Bp-QlEOGuC97Zw,1611
|
|
4
4
|
karrio/mappers/postat/settings.py,sha256=JkF6yO-sgpp6zQ7JbBjAZTf50U1l02ukQMSnaCjqm74,1094
|
|
5
|
-
karrio/plugins/postat/__init__.py,sha256=
|
|
5
|
+
karrio/plugins/postat/__init__.py,sha256=NQ3aEHSWDWoExGOadQ7ryxDH6Tu5KMhY5QJEyRuHSeg,1054
|
|
6
6
|
karrio/providers/postat/__init__.py,sha256=4hksVX0z3YuFqljwLnrMpwcCaS1k-F6vXXnrhcR7w6Y,254
|
|
7
|
-
karrio/providers/postat/error.py,sha256=
|
|
8
|
-
karrio/providers/postat/units.py,sha256=
|
|
9
|
-
karrio/providers/postat/utils.py,sha256=
|
|
7
|
+
karrio/providers/postat/error.py,sha256=ROKPQ2vKSkErkQxV3DxWsrKU1lNAAVOHh29zlea2BXE,1342
|
|
8
|
+
karrio/providers/postat/units.py,sha256=7ZDANxMPJwIuLN3FNliBspuPTtanf84z27Clvvdxy1k,7902
|
|
9
|
+
karrio/providers/postat/utils.py,sha256=_920vcSPcjQ-xHwZQbn_CoXG21l9Lq2v3GKhbl3Wh2g,2053
|
|
10
10
|
karrio/providers/postat/shipment/__init__.py,sha256=LBFK83E-DV24daViy0wFQWQGYPTSe5XvGillDp2LsZg,229
|
|
11
|
-
karrio/providers/postat/shipment/cancel.py,sha256=
|
|
12
|
-
karrio/providers/postat/shipment/create.py,sha256=
|
|
11
|
+
karrio/providers/postat/shipment/cancel.py,sha256=OdfL7DvnmidhHFXm7XKvdIRlYlDQjpU2BnsWk0MPEE0,2169
|
|
12
|
+
karrio/providers/postat/shipment/create.py,sha256=P_W0tOAJkwbXyRVFP95sYtMxPkihdAA-m2vV7SCOO6w,5917
|
|
13
13
|
karrio/schemas/postat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
14
|
karrio/schemas/postat/plc_types.py,sha256=VmqXCsiptEf2Iv48zzlal4mjd2kEmG8oCK-CTDHYHO8,155450
|
|
15
15
|
karrio/schemas/postat/void_types.py,sha256=49lZwTbVudeRiwXofLneZv8ykuJN449Q1vA7SpO1yeU,71559
|
|
16
|
-
karrio_postat-2026.1.
|
|
17
|
-
karrio_postat-2026.1.
|
|
18
|
-
karrio_postat-2026.1.
|
|
19
|
-
karrio_postat-2026.1.
|
|
20
|
-
karrio_postat-2026.1.
|
|
16
|
+
karrio_postat-2026.1.5.dist-info/METADATA,sha256=CaA4fko-65JiwA3ygB4Kb9cbquOubhs2E4KLvNRAJGM,1006
|
|
17
|
+
karrio_postat-2026.1.5.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
18
|
+
karrio_postat-2026.1.5.dist-info/entry_points.txt,sha256=-oCWdqyDuP9WWI6-l-QkY8RyPTdQdOs458D6T8adp_I,57
|
|
19
|
+
karrio_postat-2026.1.5.dist-info/top_level.txt,sha256=9Nasa6abG7pPPG8MGzlemnqw1ohIqgouzQ7HGBnOFLg,27
|
|
20
|
+
karrio_postat-2026.1.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|