Skip to content

Commit 8135212

Browse files
authored
Merge pull request #156 from purplship/apply-address-prevalidation-patches
[patch] Apply address pre-validation patches
2 parents 4824575 + 7a8ddae commit 8135212

File tree

13 files changed

+364
-212
lines changed

13 files changed

+364
-212
lines changed

requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ psycopg2-binary==2.9.1
6060
purplship==2021.10
6161
purplship.aramex==2021.10
6262
purplship.australiapost==2021.10
63-
purplship.canadapost==2021.10
63+
purplship.canadapost==2021.10.1
6464
purplship.canpar==2021.10
6565
purplship.dhl-express==2021.10
6666
purplship.dhl-universal==2021.10
@@ -72,7 +72,7 @@ purplship.purolator==2021.10
7272
purplship.royalmail==2021.10
7373
purplship.sendle==2021.10
7474
purplship.server==2021.10
75-
purplship.server.core==2021.10.1
75+
purplship.server.core==2021.10.2
7676
purplship.server.events==2021.10
7777
purplship.server.graph==2021.10
7878
purplship.server.manager==2021.10

sdk/extensions/canadapost/purplship/providers/canadapost/pickup/create.py

Lines changed: 67 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,13 @@
2525
NF,
2626
XP,
2727
)
28-
from purplship.core.models import PickupRequest, PickupDetails, Message, ChargeDetails, PickupUpdateRequest
28+
from purplship.core.models import (
29+
PickupRequest,
30+
PickupDetails,
31+
Message,
32+
ChargeDetails,
33+
PickupUpdateRequest,
34+
)
2935
from purplship.core.units import Packages
3036
from purplship.providers.canadapost.units import PackagePresets
3137
from purplship.providers.canadapost.utils import Settings
@@ -39,7 +45,9 @@ def parse_pickup_response(
3945
) -> Tuple[PickupDetails, List[Message]]:
4046
pickup = (
4147
_extract_pickup_details(response, settings)
42-
if len(response.xpath(".//*[local-name() = $name]", name="pickup-request-header"))
48+
if len(
49+
response.xpath(".//*[local-name() = $name]", name="pickup-request-header")
50+
)
4351
> 0
4452
else None
4553
)
@@ -48,21 +56,35 @@ def parse_pickup_response(
4856

4957
def _extract_pickup_details(response: Element, settings: Settings) -> PickupDetails:
5058
header = next(
51-
(XP.to_object(PickupRequestHeaderType, elt) for elt in response.xpath(".//*[local-name() = $name]", name="pickup-request-header"))
59+
(
60+
XP.to_object(PickupRequestHeaderType, elt)
61+
for elt in response.xpath(
62+
".//*[local-name() = $name]", name="pickup-request-header"
63+
)
64+
)
5265
)
5366
price = next(
54-
(XP.to_object(PickupRequestPriceType, elt) for elt in response.xpath(".//*[local-name() = $name]", name="pickup-request-price")),
55-
None
67+
(
68+
XP.to_object(PickupRequestPriceType, elt)
69+
for elt in response.xpath(
70+
".//*[local-name() = $name]", name="pickup-request-price"
71+
)
72+
),
73+
None,
5674
)
5775

58-
price_amount = sum(
59-
[
60-
NF.decimal(price.hst_amount or 0.0),
61-
NF.decimal(price.gst_amount or 0.0),
62-
NF.decimal(price.due_amount or 0.0),
63-
],
64-
0.0,
65-
) if price is not None else None
76+
price_amount = (
77+
sum(
78+
[
79+
NF.decimal(price.hst_amount or 0.0),
80+
NF.decimal(price.gst_amount or 0.0),
81+
NF.decimal(price.due_amount or 0.0),
82+
],
83+
0.0,
84+
)
85+
if price is not None
86+
else None
87+
)
6688

6789
return PickupDetails(
6890
carrier_id=settings.carrier_id,
@@ -71,19 +93,25 @@ def _extract_pickup_details(response: Element, settings: Settings) -> PickupDeta
7193
pickup_date=DF.fdate(header.next_pickup_date),
7294
pickup_charge=ChargeDetails(
7395
name="Pickup fees", amount=NF.decimal(price_amount), currency="CAD"
74-
) if price is not None else None,
96+
)
97+
if price is not None
98+
else None,
7599
)
76100

77101

78-
def pickup_request(payload: PickupRequest, settings: Settings) -> Serializable[Pipeline]:
102+
def pickup_request(
103+
payload: PickupRequest, settings: Settings
104+
) -> Serializable[Pipeline]:
79105
request: Pipeline = Pipeline(
80106
get_availability=lambda *_: _get_pickup_availability(payload),
81107
create_pickup=partial(_create_pickup, payload=payload, settings=settings),
82108
)
83109
return Serializable(request)
84110

85111

86-
def _create_pickup_request(payload: PickupRequest, settings: Settings, update: bool = False) -> Serializable[PickupRequestDetails]:
112+
def _create_pickup_request(
113+
payload: PickupRequest, settings: Settings, update: bool = False
114+
) -> Serializable[PickupRequestDetails]:
87115
"""
88116
pickup_request create a serializable typed PickupRequestDetailsType
89117
@@ -111,7 +139,7 @@ def _create_pickup_request(payload: PickupRequest, settings: Settings, update: b
111139
),
112140
city=payload.address.city,
113141
province=payload.address.state_code,
114-
postal_code=(payload.address.postal_code or "").replace(" ", ""),
142+
postal_code=(payload.address.postal_code or "").replace(" ", "").upper(),
115143
)
116144

117145
request = RequestType(
@@ -163,21 +191,37 @@ def _create_pickup_request(payload: PickupRequest, settings: Settings, update: b
163191

164192

165193
def _get_pickup_availability(payload: PickupRequest):
166-
return Job(id="availability", data=(payload.address.postal_code or "").replace(" ", ""))
194+
return Job(
195+
id="availability", data=(payload.address.postal_code or "").replace(" ", "")
196+
)
167197

168198

169-
def _create_pickup(availability_response: str, payload: PickupRequest, settings: Settings):
199+
def _create_pickup(
200+
availability_response: str, payload: PickupRequest, settings: Settings
201+
):
170202
availability = XP.to_object(pickup_availability, XP.to_xml(availability_response))
171-
data = _create_pickup_request(payload, settings) if availability.on_demand_tour else None
203+
data = (
204+
_create_pickup_request(payload, settings)
205+
if availability.on_demand_tour
206+
else None
207+
)
172208

173209
return Job(id="create_pickup", data=data, fallback="" if data is None else "")
174210

175211

176-
def _get_pickup(update_response: str, payload: PickupUpdateRequest, settings: Settings) -> Job:
212+
def _get_pickup(
213+
update_response: str, payload: PickupUpdateRequest, settings: Settings
214+
) -> Job:
177215
errors = parse_error_response(XP.to_xml(XP.bundle_xml([update_response])), settings)
178-
data = None if any(errors) else f"/enab/{settings.customer_number}/pickuprequest/{payload.confirmation_number}/details"
216+
data = (
217+
None
218+
if any(errors)
219+
else f"/enab/{settings.customer_number}/pickuprequest/{payload.confirmation_number}/details"
220+
)
179221

180-
return Job(id="get_pickup", data=Serializable(data), fallback="" if data is None else "")
222+
return Job(
223+
id="get_pickup", data=Serializable(data), fallback="" if data is None else ""
224+
)
181225

182226

183227
def _request_serializer(request: PickupRequestDetails, update: bool = False) -> str:

sdk/extensions/canadapost/purplship/providers/canadapost/rate.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,8 @@
1010
united_statesType,
1111
internationalType,
1212
price_quoteType,
13-
service_standardType,
1413
)
15-
from functools import reduce
16-
from typing import List, Tuple, cast
14+
from typing import List, Tuple
1715
from purplship.core.utils import Serializable, Element, NF, XP
1816
from purplship.providers.canadapost.utils import Settings
1917
from purplship.core.units import Country, Currency, Packages, Services, Options
@@ -84,8 +82,8 @@ def rate_request(
8482
package = Packages(payload.parcels, PackagePresets, required=["weight"]).single
8583
services = Services(payload.services, ServiceType)
8684
options = Options(payload.options, OptionCode)
87-
recipient_postal_code = (payload.recipient.postal_code or "").replace(" ", "")
88-
shipper_postal_code = (payload.shipper.postal_code or "").replace(" ", "")
85+
recipient_postal_code = (payload.recipient.postal_code or "").replace(" ", "").upper()
86+
shipper_postal_code = (payload.shipper.postal_code or "").replace(" ", "").upper()
8987

9088
request = mailing_scenario(
9189
customer_number=settings.customer_number,

sdk/extensions/canadapost/purplship/providers/canadapost/shipment/contract.py

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -62,36 +62,48 @@ def _extract_shipment(response: Element, settings: Settings) -> ShipmentDetails:
6262
carrier_id=settings.carrier_id,
6363
tracking_number=info.tracking_pin,
6464
shipment_identifier=info.tracking_pin,
65-
label=getattr(label, "text", None)
65+
label=getattr(label, "text", None),
6666
)
6767

6868

6969
def shipment_request(
7070
payload: ShipmentRequest, settings: Settings
7171
) -> Serializable[ShipmentType]:
72-
package = Packages(payload.parcels, PackagePresets, required=['weight']).single
72+
package = Packages(payload.parcels, PackagePresets, required=["weight"]).single
7373
service = ServiceType.map(payload.service).value_or_key
7474
options = Options(payload.options, OptionCode)
7575

7676
is_intl = (
77-
payload.recipient.country_code is not None and
78-
payload.recipient.country_code != 'CA'
77+
payload.recipient.country_code is not None
78+
and payload.recipient.country_code != "CA"
7979
)
80-
payment_type = PaymentType.map(getattr(payload.payment, 'paid_by', None)).value
80+
payment_type = PaymentType.map(getattr(payload.payment, "paid_by", None)).value
8181
all_options = (
82-
[*options, (OptionCode.canadapost_return_to_sender.name, OptionCode.canadapost_return_to_sender.value.apply(True))]
83-
if is_intl and not any(key in options for key in INTERNATIONAL_NON_DELIVERY_OPTION) else [*options]
82+
[
83+
*options,
84+
(
85+
OptionCode.canadapost_return_to_sender.name,
86+
OptionCode.canadapost_return_to_sender.value.apply(True),
87+
),
88+
]
89+
if is_intl
90+
and not any(key in options for key in INTERNATIONAL_NON_DELIVERY_OPTION)
91+
else [*options]
8492
)
8593
customs = payload.customs
86-
duty = getattr(customs, 'duty', Duty())
87-
label_encoding, label_format = LabelType[payload.label_type or 'PDF_4x6'].value
94+
duty = getattr(customs, "duty", Duty())
95+
label_encoding, label_format = LabelType[payload.label_type or "PDF_4x6"].value
96+
recipient_postal_code = (
97+
(payload.recipient.postal_code or "").replace(" ", "").upper()
98+
)
99+
shipper_postal_code = (payload.shipper.postal_code or "").replace(" ", "").upper()
88100

89101
request = ShipmentType(
90102
customer_request_id=None,
91103
groupIdOrTransmitShipment=groupIdOrTransmitShipment(),
92104
quickship_label_requested=None,
93105
cpc_pickup_indicator=None,
94-
requested_shipping_point=(payload.shipper.postal_code or "").replace(" ", ""),
106+
requested_shipping_point=shipper_postal_code,
95107
shipping_point_id=None,
96108
expected_mailing_date=options.shipment_date,
97109
provide_pricing_info=True,
@@ -106,9 +118,13 @@ def shipment_request(
106118
city=payload.shipper.city,
107119
prov_state=payload.shipper.state_code,
108120
country_code=payload.shipper.country_code,
109-
postal_zip_code=(payload.shipper.postal_code or "").replace(" ", ""),
110-
address_line_1=SF.concat_str(payload.shipper.address_line1, join=True),
111-
address_line_2=SF.concat_str(payload.shipper.address_line2, join=True),
121+
postal_zip_code=shipper_postal_code,
122+
address_line_1=SF.concat_str(
123+
payload.shipper.address_line1, join=True
124+
),
125+
address_line_2=SF.concat_str(
126+
payload.shipper.address_line2, join=True
127+
),
112128
),
113129
),
114130
destination=DestinationType(
@@ -120,7 +136,7 @@ def shipment_request(
120136
city=payload.recipient.city,
121137
prov_state=payload.recipient.state_code,
122138
country_code=payload.recipient.country_code,
123-
postal_zip_code=(payload.recipient.postal_code or "").replace(" ", ""),
139+
postal_zip_code=recipient_postal_code,
124140
address_line_1=SF.concat_str(
125141
payload.recipient.address_line1, join=True
126142
),
@@ -143,15 +159,17 @@ def shipment_request(
143159
optionsType(
144160
option=[
145161
OptionType(
146-
option_code=getattr(option, 'key', option),
147-
option_amount=getattr(option, 'value', None),
162+
option_code=getattr(option, "key", option),
163+
option_amount=getattr(option, "value", None),
148164
option_qualifier_1=None,
149165
option_qualifier_2=None,
150166
)
151-
for code, option in all_options if code in OptionCode
167+
for code, option in all_options
168+
if code in OptionCode
152169
]
153170
)
154-
if any(all_options) else None
171+
if any(all_options)
172+
else None
155173
),
156174
notification=(
157175
NotificationType(
@@ -160,7 +178,8 @@ def shipment_request(
160178
on_exception=True,
161179
on_delivery=True,
162180
)
163-
if options.email_notification and any([options.email_notification_to, payload.recipient.email])
181+
if options.email_notification
182+
and any([options.email_notification_to, payload.recipient.email])
164183
else None
165184
),
166185
print_preferences=PrintPreferencesType(
@@ -200,14 +219,17 @@ def shipment_request(
200219
for item in customs.commodities
201220
]
202221
)
203-
) if any(customs.commodities or []) else None
222+
)
223+
if any(customs.commodities or [])
224+
else None,
204225
)
205-
if customs is not None else None
226+
if customs is not None
227+
else None
206228
),
207229
references=ReferencesType(
208230
cost_centre=payload.reference,
209231
customer_ref_1=payload.reference,
210-
customer_ref_2=getattr(payload, 'id', None),
232+
customer_ref_2=getattr(payload, "id", None),
211233
),
212234
settlement_info=SettlementInfoType(
213235
paid_by_customer=(

0 commit comments

Comments
 (0)