Skip to content

Commit c990a64

Browse files
authored
Merge pull request #79 from PurplShip/purplship-2020.9.0
[release] Purplship SDK 2020.9.0
2 parents 5ce5be2 + 588539c commit c990a64

File tree

203 files changed

+7382
-2301
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

203 files changed

+7382
-2301
lines changed

README.md

Lines changed: 311 additions & 254 deletions
Large diffs are not rendered by default.

cli.py

Lines changed: 37 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@
3333
{% endfor %}
3434
''')
3535

36+
PACKAGING_TYPES_TEMPLATE = Template('''
37+
{% for key, value in option_mappers.items() %}
38+
- <a name="options-{{ key }}"></a> {{ mappers[key]["label"] }}
39+
Code | Identifier
40+
--- | ---
41+
{% for code, name in value.items() %} | `{{ code }}` | {{ name }}
42+
{% endfor %}
43+
{% endfor %}
44+
''')
45+
3646
SHIPMENT_PRESETS_TEMPLATE = Template('''
3747
{% for key, value in preset_mappers.items() %}
3848
- <a name="presets-{{ key }}"></a> {{ mappers[key]["label"] }}
@@ -54,40 +64,49 @@ def import_pkg(pkg: str):
5464

5565

5666
PACKAGE_MAPPERS = {
67+
'purplship': {
68+
'label': "Multi-carrier (Purplship)",
69+
'package': import_pkg('purplship.core.units'),
70+
'packagingTypes': "PackagingUnit"
71+
},
5772
'canadapost': {
5873
'label': "Canada Post",
5974
'package': import_pkg('purplship.providers.canadapost.units'),
6075
'services': "ServiceType",
6176
'options': "OptionCode",
6277
'packagePresets': "PackagePresets"
6378
},
64-
'dhl': {
65-
'label': "DHL",
66-
'package': import_pkg('purplship.providers.dhl.units'),
79+
'dhl_express': {
80+
'label': "DHL Express",
81+
'package': import_pkg('purplship.providers.dhl_express.units'),
6782
'services': "Product",
6883
'options': "SpecialServiceCode",
69-
'packagePresets': "PackagePresets"
84+
'packagePresets': "PackagePresets",
85+
'packagingTypes': "DCTPackageType"
7086
},
7187
'fedex': {
7288
'label': "FedEx",
7389
'package': import_pkg('purplship.providers.fedex.units'),
7490
'services': "ServiceType",
7591
'options': "SpecialServiceType",
76-
'packagePresets': "PackagePresets"
92+
'packagePresets': "PackagePresets",
93+
'packagingTypes': "PackagingType"
7794
},
7895
'purolator': {
7996
'label': "Purolator",
8097
'package': import_pkg('purplship.providers.purolator.units'),
8198
'services': "Product",
8299
'options': "Service",
83-
'packagePresets': "PackagePresets"
100+
'packagePresets': "PackagePresets",
101+
'packagingTypes': "PackagingType"
84102
},
85103
'ups': {
86104
'label': "UPS",
87105
'package': import_pkg('purplship.providers.ups.units'),
88106
'services': "ShippingServiceCode",
89107
'options': "ServiceOption",
90-
'packagePresets': "PackagePresets"
108+
'packagePresets': "PackagePresets",
109+
'packagingTypes': "RatingPackagingType"
91110
}
92111
}
93112

@@ -127,6 +146,16 @@ def generate_services():
127146
click.echo(SERVICES_TEMPLATE.render(service_mappers=service_mappers, mappers=PACKAGE_MAPPERS))
128147

129148

149+
@cli.command()
150+
def generate_packaging_types():
151+
service_mappers = {
152+
key: {c.name: c.value for c in list(getattr(mapper['package'], mapper['packagingTypes']))}
153+
for key, mapper in PACKAGE_MAPPERS.items()
154+
if mapper.get('packagingTypes') is not None
155+
}
156+
click.echo(SERVICES_TEMPLATE.render(service_mappers=service_mappers, mappers=PACKAGE_MAPPERS))
157+
158+
130159
@cli.command()
131160
def generate_models():
132161
import purplship.core.models as m
@@ -157,4 +186,4 @@ def generate_models():
157186

158187

159188
if __name__ == '__main__':
160-
cli()
189+
cli()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from purplship.mappers.canadapost.mapper import Mapper
2+
from purplship.mappers.canadapost.proxy import Proxy
3+
from purplship.mappers.canadapost.settings import Settings

extensions/dhl/purplship/freight/mappers/dhl/mapper.py renamed to extensions/canadapost/purplship/mappers/canadapost/mapper.py

Lines changed: 42 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,82 +1,88 @@
11
from typing import List, Tuple
2-
from pydhl.dct_req_global_2_0 import DCTRequest
3-
from pydhl.ship_val_global_req_6_2 import ShipmentRequest as DHLShipmentRequest
4-
from pydhl.tracking_request_known_1_0 import KnownTrackingRequest
5-
from pydhl.book_pickup_global_req_3_0 import BookPURequest
6-
from pydhl.modify_pickup_global_req_3_0 import ModifyPURequest
7-
from pydhl.cancel_pickup_global_req_3_0 import CancelPURequest
8-
from purplship.freight.mapper import Mapper as BaseMapper
2+
from pycanadapost.rating import mailing_scenario
3+
from pycanadapost.pickuprequest import (
4+
PickupRequestDetailsType,
5+
PickupRequestResponseDetailsType,
6+
)
7+
from purplship.core.utils.pipeline import Pipeline
98
from purplship.core.utils.serializable import Serializable, Deserializable
9+
from purplship.api.mapper import Mapper as BaseMapper
1010
from purplship.core.models import (
11-
RateRequest,
12-
RateDetails,
11+
ShipmentRequest,
1312
TrackingRequest,
13+
Message,
1414
TrackingDetails,
15-
ShipmentRequest,
15+
RateDetails,
16+
RateRequest,
1617
ShipmentDetails,
1718
PickupRequest,
1819
PickupDetails,
1920
PickupUpdateRequest,
2021
PickupCancellationRequest,
21-
Message,
22+
ConfirmationDetails,
2223
)
23-
from purplship.providers.dhl import (
24-
dct_request,
25-
parse_dct_response,
26-
known_tracking_request,
27-
parse_known_tracking_response,
24+
from purplship.providers.canadapost import (
25+
mailing_scenario_request,
26+
parse_price_quotes,
27+
tracking_pins_request,
28+
parse_tracking_summary,
2829
shipment_request,
2930
parse_shipment_response,
30-
book_pickup_request,
31-
parse_book_pickup_response,
3231
cancel_pickup_request,
32+
create_pickup_request,
33+
update_pickup_request,
34+
parse_pickup_response,
3335
parse_cancel_pickup_response,
34-
modify_pickup_request,
35-
parse_modify_pickup_response,
3636
)
37-
from purplship.freight.mappers.dhl.settings import Settings
37+
from purplship.mappers.canadapost.settings import Settings
3838

3939

4040
class Mapper(BaseMapper):
4141
settings: Settings
4242

43-
def create_rate_request(self, payload: RateRequest) -> Serializable[DCTRequest]:
44-
return dct_request(payload, self.settings)
43+
"""Request Mappers"""
44+
45+
def create_rate_request(
46+
self, payload: RateRequest
47+
) -> Serializable[mailing_scenario]:
48+
return mailing_scenario_request(payload, self.settings)
4549

4650
def create_tracking_request(
4751
self, payload: TrackingRequest
48-
) -> Serializable[KnownTrackingRequest]:
49-
return known_tracking_request(payload, self.settings)
52+
) -> Serializable[List[str]]:
53+
return tracking_pins_request(payload)
5054

5155
def create_shipment_request(
5256
self, payload: ShipmentRequest
53-
) -> Serializable[DHLShipmentRequest]:
57+
) -> Serializable[Pipeline]:
5458
return shipment_request(payload, self.settings)
5559

5660
def create_pickup_request(
5761
self, payload: PickupRequest
58-
) -> Serializable[BookPURequest]:
59-
return book_pickup_request(payload, self.settings)
62+
) -> Serializable[PickupRequestDetailsType]:
63+
return create_pickup_request(payload, self.settings)
6064

6165
def create_modify_pickup_request(
6266
self, payload: PickupUpdateRequest
63-
) -> Serializable[ModifyPURequest]:
64-
return modify_pickup_request(payload, self.settings)
67+
) -> Serializable[PickupRequestResponseDetailsType]:
68+
return update_pickup_request(payload, self.settings)
6569

6670
def create_cancel_pickup_request(
6771
self, payload: PickupCancellationRequest
68-
) -> Serializable[CancelPURequest]:
72+
) -> Serializable[str]:
6973
return cancel_pickup_request(payload, self.settings)
7074

75+
"""Response Parsers"""
76+
7177
def parse_rate_response(
7278
self, response: Deserializable[str]
7379
) -> Tuple[List[RateDetails], List[Message]]:
74-
return parse_dct_response(response.deserialize(), self.settings)
80+
return parse_price_quotes(response.deserialize(), self.settings)
7581

7682
def parse_tracking_response(
7783
self, response: Deserializable[str]
7884
) -> Tuple[List[TrackingDetails], List[Message]]:
79-
return parse_known_tracking_response(response.deserialize(), self.settings)
85+
return parse_tracking_summary(response.deserialize(), self.settings)
8086

8187
def parse_shipment_response(
8288
self, response: Deserializable[str]
@@ -86,14 +92,14 @@ def parse_shipment_response(
8692
def parse_pickup_response(
8793
self, response: Deserializable[str]
8894
) -> Tuple[PickupDetails, List[Message]]:
89-
return parse_book_pickup_response(response.deserialize(), self.settings)
95+
return parse_pickup_response(response.deserialize(), self.settings)
9096

9197
def parse_modify_pickup_response(
9298
self, response: Deserializable[str]
9399
) -> Tuple[PickupDetails, List[Message]]:
94-
return parse_modify_pickup_response(response.deserialize(), self.settings)
100+
return parse_pickup_response(response.deserialize(), self.settings)
95101

96102
def parse_cancel_pickup_response(
97103
self, response: Deserializable[str]
98-
) -> Tuple[dict, List[Message]]:
104+
) -> Tuple[ConfirmationDetails, List[Message]]:
99105
return parse_cancel_pickup_response(response.deserialize(), self.settings)

extensions/canadapost/purplship/package/mappers/canadapost/proxy.py renamed to extensions/canadapost/purplship/mappers/canadapost/proxy.py

Lines changed: 76 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
exec_parrallel,
1010
bundle_xml,
1111
)
12-
from purplship.package.mappers.canadapost.settings import Settings
13-
from purplship.package.proxy import Proxy as BaseProxy
12+
from purplship.mappers.canadapost.settings import Settings
13+
from purplship.api.proxy import Proxy as BaseProxy
1414
from pycanadapost.rating import mailing_scenario
1515

1616

@@ -88,16 +88,16 @@ def _get_label(job: Job):
8888
},
8989
method="GET",
9090
)
91-
return f'<label>{label_string}</label>'
91+
return f"<label>{label_string}</label>"
9292

9393
def process(job: Job):
9494
if job.data is None:
9595
return job.fallback
9696

9797
subprocess = {
98-
'contract_shipment': _contract_shipment,
99-
'non_contract_shipment': _non_contract_shipment,
100-
'shipment_label': _get_label
98+
"contract_shipment": _contract_shipment,
99+
"non_contract_shipment": _non_contract_shipment,
100+
"shipment_label": _get_label,
101101
}
102102
if job.id not in subprocess:
103103
raise PurplShipError(f"Unknown shipment request job id: {job.id}")
@@ -108,3 +108,73 @@ def process(job: Job):
108108
response = pipeline.apply(process)
109109

110110
return Deserializable(bundle_xml(response), to_xml)
111+
112+
def request_pickup(self, request: Serializable[Pipeline]) -> Deserializable[str]:
113+
def _availability(job: Job) -> str:
114+
return http(
115+
url=f"{self.settings.server_url}/ad/pickup/pickupavailability/{job.data}",
116+
headers={
117+
"Accept": "application/vnd.cpc.pickup+xml",
118+
"Authorization": f"Basic {self.settings.authorization}",
119+
"Accept-language": "en-CA",
120+
},
121+
method="GET",
122+
)
123+
124+
def _create_pickup(job: Job) -> str:
125+
return http(
126+
url=f"{self.settings.server_url}/enab/{self.settings.customer_number}/pickuprequest",
127+
data=bytearray(job.data.serialize(), "utf-8"),
128+
headers={
129+
"Accept": "application/vnd.cpc.pickuprequest+xml",
130+
"Content-Type": "application/vnd.cpc.pickuprequest+xml",
131+
"Authorization": f"Basic {self.settings.authorization}",
132+
"Accept-language": "en-CA",
133+
},
134+
method="POST",
135+
)
136+
137+
def process(job: Job):
138+
if job.data is None:
139+
return job.fallback
140+
141+
subprocess = {
142+
"create_pickup": _create_pickup,
143+
"availability": _availability,
144+
}
145+
if job.id not in subprocess:
146+
raise PurplShipError(f"Unknown pickup request job id: {job.id}")
147+
148+
return subprocess[job.id](job)
149+
150+
pipeline: Pipeline = request.serialize()
151+
response = pipeline.apply(process)
152+
153+
return Deserializable(bundle_xml(response), to_xml)
154+
155+
def modify_pickup(self, request: Serializable[dict]) -> Deserializable[str]:
156+
payload = request.serialize()
157+
response = http(
158+
url=f"{self.settings.server_url}/enab/{self.settings.customer_number}/pickuprequest/{payload['pickuprequest']}",
159+
data=bytearray(payload["data"], "utf-8"),
160+
headers={
161+
"Accept": "application/vnd.cpc.pickuprequest+xml",
162+
"Authorization": f"Basic {self.settings.authorization}",
163+
"Accept-language": "en-CA",
164+
},
165+
method="PUT",
166+
)
167+
return Deserializable(response, to_xml)
168+
169+
def cancel_pickup(self, request: Serializable[str]) -> Deserializable[str]:
170+
pickuprequest = request.serialize()
171+
response = http(
172+
url=f"{self.settings.server_url}/enab/{self.settings.customer_number}/pickuprequest/{pickuprequest}",
173+
headers={
174+
"Accept": "application/vnd.cpc.pickuprequest+xml",
175+
"Authorization": f"Basic {self.settings.authorization}",
176+
"Accept-language": "en-CA",
177+
},
178+
method="DELETE",
179+
)
180+
return Deserializable(response or "<wrapper></wrapper>", to_xml)

extensions/canadapost/purplship/package/mappers/canadapost/settings.py renamed to extensions/canadapost/purplship/mappers/canadapost/settings.py

File renamed without changes.

extensions/canadapost/purplship/package/mappers/canadapost/__init__.py

Lines changed: 0 additions & 3 deletions
This file was deleted.

0 commit comments

Comments
 (0)