Skip to content

Commit

Permalink
Merge pull request akretion#163 from akretion/dpd_bc
Browse files Browse the repository at this point in the history
Implement new DPD GeoLabel "Bc" API
  • Loading branch information
florian-dacosta authored Jun 25, 2023
2 parents 79db223 + 64992a4 commit 9ec96b2
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 39 deletions.
6 changes: 6 additions & 0 deletions roulier/carriers/dpd_fr_soap/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,12 @@ def _service(self):
# 'description': 'Drop-off Location id (Relais Colis)'
}

# Whether to use the legacy DPD API or the new GeoLabel compatible one
schema["legacy"] = {
"required": False,
"default": False,
}

return schema

def _address(self):
Expand Down
8 changes: 3 additions & 5 deletions roulier/carriers/dpd_fr_soap/carrier_action.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,18 @@
from .transport import DpdTransport


class DpdGetabel(CarrierGetLabel):
class DpdGetLabel(CarrierGetLabel):
"""Implementation for Dpd."""

ws_url = (
"https://e-station.cargonet.software/dpd-eprintwebservice/eprintwebservice.asmx"
)
ws_test_url = (
"http://92.103.148.116/exa-eprintwebservice/eprintwebservice.asmx?WSDL"
)
ws_test_url = "https://e-station-testenv.cargonet.software/eprintwebservice/eprintwebservice.asmx"
encoder = DpdEncoder
decoder = DpdDecoder
transport = DpdTransport
api = DpdApi
manage_multi_label = False


factory.register_builder("dpd_fr_soap", "get_label", DpdGetabel)
factory.register_builder("dpd_fr_soap", "get_label", DpdGetLabel)
64 changes: 45 additions & 19 deletions roulier/carriers/dpd_fr_soap/decoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,49 @@ class DpdDecoder(DecoderGetLabel):
def decode(self, response, input_payload):
"""Understand a CreateShipmentWithLabelsResponse."""
output_format = input_payload["output_format"]
is_legacy = input_payload["is_legacy"]
xml = objectify.fromstring(response["body"])
shipments, files = xml.CreateShipmentWithLabelsResult.getchildren()
shipment = shipments.getchildren()[0]
label_file, summary_file = files.getchildren()
parcel = {
"id": 1,
"reference": self._get_parcel_number(input_payload)
or shipment.parcelnumber.text,
"tracking": {"number": shipment.barcode.text, "url": "", "partner": "",},
"label": { # same as main label
"data": label_file.label.text,
"name": "label 1",
"type": output_format,
},
}
annexes = [
{"data": summary_file.label.text, "name": "Summary", "type": output_format}
]
self.result["parcels"].append(parcel)
self.result["annexes"] += annexes

shipments, files = getattr(
xml, "CreateShipmentWithLabels%sResult" % ("" if is_legacy else "Bc")
).getchildren()

if is_legacy:
shipment = shipments.getchildren()[0]
parcel_field = "parcelnumber"
barcode_field = "barcode"
else:
shipmentbc = shipments.getchildren()[0]
shipment = shipmentbc.getchildren()[0]
parcel_field = "BarcodeId"
barcode_field = "BarCode"

annexes = []
for dpdfile in files.getchildren():
# label file : EPRINT legacy type, BIC3 geolabel type
if dpdfile.type.text in ("EPRINT", "BIC3"):
parcel = {
"id": 1,
"reference": self._get_parcel_number(input_payload)
or getattr(shipment, parcel_field).text,
"tracking": {
"number": getattr(shipment, barcode_field).text,
"url": "",
"partner": "",
},
"label": { # same as main label
"data": dpdfile.label.text,
"name": "label 1",
"type": output_format,
},
}
self.result["parcels"].append(parcel)
# summary file (EPRINTATTACHMENT) or any other file but not supported yet.
else:
self.result["annexes"].append(
{
"data": dpdfile.label.text,
"name": "Summary",
"type": output_format,
}
)
3 changes: 3 additions & 0 deletions roulier/carriers/dpd_fr_soap/encoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ def reduce_address(address):
reduce_address(data["from_address"])

output_format = data["service"]["labelFormat"]
is_legacy = data["service"]["legacy"]
# if data["service"]["labelFormat"] in ("PNG", "ZPL"):
if data["service"]["labelFormat"] == "PNG":
# WS doesn't handle zpl yet, we convert it later
Expand All @@ -58,7 +59,9 @@ def reduce_address(address):
parcel=data["parcels"][0],
sender_address=data["from_address"],
receiver_address=data["to_address"],
legacy=is_legacy,
),
"headers": data["auth"],
"output_format": output_format,
"is_legacy": is_legacy,
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<car:CreateShipmentWithLabels xmlns:car="http://www.cargonet.software">
<car:CreateShipmentWithLabels{{ '' if legacy else 'Bc'}} xmlns:car="http://www.cargonet.software">
<car:request>
{% with address = receiver_address %}
<car:receiveraddress>
Expand Down Expand Up @@ -33,7 +33,7 @@
</car:services>

<car:labelType>
<car:type>{{ service.labelFormat }}</car:type>
<car:type>{{ service.labelFormat }}</car:type>
</car:labelType>
<car:customer_countrycode>{{ service.customerCountry }}</car:customer_countrycode>
<car:customer_centernumber>{{ service.agencyId }}</car:customer_centernumber>
Expand All @@ -44,4 +44,4 @@
<car:reference2>{{ service.reference2 }}</car:reference2>
<car:reference3>{{ service.reference3 }}</car:reference3>
</car:request>
</car:CreateShipmentWithLabels>
</car:CreateShipmentWithLabels{{ '' if legacy else 'Bc'}}>
36 changes: 26 additions & 10 deletions roulier/carriers/dpd_fr_soap/tests/test_dpd.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import logging
import copy
import re
import pytest

from roulier import roulier
from roulier.exception import InvalidApiInput, CarrierError
Expand All @@ -13,6 +14,11 @@
EXCEPTION_MESSAGE = "Failed call with parameters %s"


@pytest.fixture(params=[False, True])
def legacy(request):
return request.param


def _test_ip_allowed(REQUIRE_ALLOWED=True):
def canceled_test():
if REQUIRE_ALLOWED:
Expand Down Expand Up @@ -67,15 +73,17 @@ def test_dpd_invalid_ip():


@_test_ip_allowed(True)
def test_dpd_classic():
def test_dpd_classic(legacy):
vals = copy.deepcopy(DATA)
vals["service"]["legacy"] = legacy
result = roulier.get("dpd_fr_soap", "get_label", vals)
assert_result(vals, result, 1, 1)


@_test_ip_allowed(True)
def test_predict():
def test_predict(legacy):
vals = copy.deepcopy(DATA)
vals["service"]["legacy"] = legacy
vals["service"]["product"] = "DPD_Predict"
with assert_raises(
InvalidApiInput, {"service": [{"notifications": "must be set to Predict"}]}
Expand All @@ -99,48 +107,54 @@ def test_predict():


@_test_ip_allowed(True)
def test_dpd_format_pdf():
def test_dpd_format_pdf(legacy):
vals = copy.deepcopy(DATA)
vals["service"]["legacy"] = legacy
vals["service"]["labelFormat"] = "PDF"
result = roulier.get("dpd_fr_soap", "get_label", vals)
assert_result(vals, result, 1, 1, "PDF")


@_test_ip_allowed(True)
def test_dpd_format_pdf_a6():
def test_dpd_format_pdf_a6(legacy):
vals = copy.deepcopy(DATA)
vals["service"]["legacy"] = legacy
vals["service"]["labelFormat"] = "PDF_A6"
result = roulier.get("dpd_fr_soap", "get_label", vals)
assert_result(vals, result, 1, 1, "PDF_A6")


@_test_ip_allowed(True)
def test_dpd_format_png():
def test_dpd_format_png(legacy):
vals = copy.deepcopy(DATA)
vals["service"]["legacy"] = legacy
vals["service"]["labelFormat"] = "PNG"
result = roulier.get("dpd_fr_soap", "get_label", vals)
assert_result(vals, result, 1, 1, "PNG")


@_test_ip_allowed(True)
def test_dpd_format_zpl():
def test_dpd_format_zpl(legacy):
vals = copy.deepcopy(DATA)
vals["service"]["legacy"] = legacy
vals["service"]["labelFormat"] = "ZPL"
result = roulier.get("dpd_fr_soap", "get_label", vals)
assert_result(vals, result, 1, 1, "ZPL")


@_test_ip_allowed(True)
def test_dpd_format_invalid():
def test_dpd_format_invalid(legacy):
vals = copy.deepcopy(DATA)
vals["service"]["legacy"] = legacy
vals["service"]["labelFormat"] = "invalid"
with assert_raises(InvalidApiInput, {"service": [{"labelFormat": "unallowed"}]}):
result = roulier.get("dpd_fr_soap", "get_label", vals)


@_test_ip_allowed(True)
def test_common_failed_get_label():
def test_common_failed_get_label(legacy):
vals = copy.deepcopy(DATA)
vals["service"]["legacy"] = legacy
# Weight
vals["parcels"][0]["weight"] = 999.99
with assert_raises(CarrierError, [{"id": "InvalidWeight"}]):
Expand All @@ -158,16 +172,18 @@ def test_common_failed_get_label():


@_test_ip_allowed(True)
def test_auth():
def test_auth(legacy):
vals = copy.deepcopy(DATA)
vals["service"]["legacy"] = legacy
vals["auth"]["login"] = "test"
with assert_raises(CarrierError, [{"id": "PermissionDenied"}]):
roulier.get("dpd_fr_soap", "get_label", vals)


@_test_ip_allowed(True)
def test_relai():
def test_relai(legacy):
vals = copy.deepcopy(DATA)
vals["service"]["legacy"] = legacy
vals["service"]["product"] = "DPD_Relais"
with assert_raises(
InvalidApiInput, {"service": [{"pickupLocationId": "mandatory"}]}
Expand Down
12 changes: 10 additions & 2 deletions roulier/transport.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
"""Send a request to a carrier and get the result."""
from abc import ABC, abstractmethod
import logging
import os
import requests
from abc import ABC, abstractmethod
from .exception import CarrierError
import logging

log = logging.getLogger(__name__)

Expand All @@ -28,6 +29,13 @@ def before_ws_call_transform_payload(self, payload):
def send(self, payload):
request_kwargs = self.before_ws_call_prepare_request_kwargs(payload)
log.debug(request_kwargs["body"])

if os.environ.get("ROULIER_PROXY"):
request_kwargs["proxies"] = {
"http": os.environ["ROULIER_PROXY"],
"https": os.environ["ROULIER_PROXY"],
}

response = self.send_request(**request_kwargs)
log.debug("WS response time %s" % response.elapsed.total_seconds())
return self.handle_response(response)
Expand Down

0 comments on commit 9ec96b2

Please sign in to comment.