Skip to content

Commit

Permalink
Improve api
Browse files Browse the repository at this point in the history
  • Loading branch information
hparfr committed Sep 2, 2019
1 parent 0ff7e0c commit 3017395
Show file tree
Hide file tree
Showing 4 changed files with 213 additions and 107 deletions.
205 changes: 184 additions & 21 deletions roulier/carriers/geodis/geodis_api_rest_ws.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,35 +11,198 @@ def _schemas(self):
'auth': self._auth(),
}

def normalize(self, data):
externalApi = super(GeodisApiRestWs, self)
internalApi = self._interal_api()
step1 = externalApi.normalize(data)
step2 = internalApi.normalize(step1)
return step2

class GeodisApiTrackingList(GeodisApiRestWs):
def _service(self):
schema = {
"dateDepart": {"type": "string", "default": "", "empty": True},
"dateDepartDebut": {"type": "string", "default": "", "empty": True},
"dateDepartFin": {"type": "string", "default": "", "empty": True},
"noRecepisse": {"type": "string", "default": "", "empty": True},
"reference1": {"type": "string", "default": "", "empty": True},
"cabColis": {"type": "string", "default": "", "empty": True},
"noSuivi": {"type": "string", "default": "", "empty": True},
"codeSa": {"type": "string", "default": "", "empty": True},
"codeClient": {"type": "string", "default": "", "empty": True},
"codeProduit": {"type": "string", "default": "", "empty": True},
"typePrestation": {"type": "string", "default": "", "empty": True},
"dateLivraison": {"type": "string", "default": "", "empty": True},
"refDest": {"type": "string", "default": "", "empty": True},
"nomDest": {"type": "string", "default": "", "empty": True},
"codePostalDest": {"type": "string", "default": "", "empty": True},
"natureMarchandise": {"type": "string", "default": "", "empty": True},
def _interal_api(self):
pass


class GeodisMappingIn(Api):
"""Internal API"""

def flatten(self, data, out):
for (key, val) in data.items():
if isinstance(val, dict):
self.flatten(val, out)
else:
out[key] = val

def normalize(self, data):
without_auth = {
key: val
for (key, val) in data.items()
if key != 'auth'
}
return schema
flat = {
'auth': data['auth'],
'service': {}
}
self.flatten(without_auth, flat['service'])
normalized = super(GeodisMappingIn, self).normalize(flat)
return normalized


class GeodisApiTrackingListMapping(GeodisMappingIn):
"""Internal API
Used to rename fields."""
def _schemas(self):
return {"service": {
"shippingDate": {"rename": "dateDepart"},
"shippingDateStart": {"rename": "dateDepartDebut"},
"shippingDateEnd": {"rename": "dateDepartFin"},
"agencyId": {"rename": "codeSa"},
"customerId": {"rename": "codeClient"},
"reference1": {"rename": "reference1"},
"reference2": {"rename": "refDest"},
"name": {"rename": "nomDest"},
"zip": {"rename": "codePostalDest"},
'estDeliveryDate': {"rename": 'dateLivraison'},
"shippingId": {"rename": "noRecepisse"},
"barcode": {"rename": "cabColis"},
"trackingId": {"rename": "noSuivi"},
}}


class GeodisApiTrackingMapping(GeodisMappingIn):
"""Internal API
Used to rename fields."""
def _schemas(self):
return {"service": {
"trackingId": {"rename": "noSuivi"},
}}


class GeodisApiTracking(GeodisApiRestWs):

def _service(self):
schema = {
"refUniExp": {"type": "string", "default": "", "empty": True},
"noSuivi": {"type": "string", "default": "", "empty": True},
"trackingId": {"type": "string", "default": "", "empty": True},
}
return schema

def _interal_api(self):
return GeodisApiTrackingMapping()


class GeodisApiTrackingList(GeodisApiRestWs):
def _service(self):
return {
"shippingDate": {"type": "string", "default": "", "empty": True},
"shippingDateStart": {"type": "string", "default": "", "empty": True},
"shippingDateEnd": {"type": "string", "default": "", "empty": True},
"agencyId": {"type": "string", "default": "", "empty": True},
"customerId": {"type": "string", "default": "", "empty": True},
"reference1": {"type": "string", "default": "", "empty": True},
"reference2": {"type": "string", "default": "", "empty": True},
}

def _tracking(self):
return {
"estDeliveryDate": {"type": "string", "default": "", "empty": True},
"shippingId": {"type": "string", "default": "", "empty": True},
"barcode": {"type": "string", "default": "", "empty": True},
"trackingId": {"type": "string", "default": "", "empty": True},
}

def _to_address(self):
return {
"name": {"type": "string", "default": "", "empty": True},
"zip": {"type": "string", "default": "", "empty": True},
}

def _schemas(self):
schema = super(GeodisApiTrackingList, self)._schemas()
schema['tracking'] = self._tracking()
schema['to_address'] = self._to_address()
return schema

def _interal_api(self):
return GeodisApiTrackingListMapping()


class GeodisMappingOut(Api):

def normalize(self, data):
schema = self.schema()
# self.add_tracking_code(data)
return self.visit(data, schema)

def visit(self, data, schema):
out = {}
for (key, val) in schema.items():
if isinstance(val, dict):
out[key] = self.visit(data, val)
else:
out[key] = data[val]
return out


class GeodisApiTrackingListOut(GeodisMappingOut):

def to_address(self):
return {
'street1': 'adresse1Dest',
'street2': 'adresse2Dest',
'country': 'codePaysDest',
'zip': 'codePostalDest',
'country_name': 'libellePaysDest',
'name': 'nomDest',
'city': 'villeDest',
}

def from_address(self):
return {
'street1': 'adresse1Exp',
'street2': 'adresse2Exp',
'country': 'codePaysExp',
'zip': 'codePostalExp',
'country_name': 'libellePaysExp',
'name': 'nomExp',
'city': 'villeExp',
}

def parcels(self):
return {
'weight': 'poids',
}

def service(self):
return {
"product": 'codeProduit',
"agencyId": 'codeSa',
"customerId": 'codeClient',
"shippingId": 'noRecepisse',
'shippingDate': 'dateDepart',
'reference1': 'reference1',
'reference2': 'reference2',
'reference3': 'refDest',
'option': 'codeOption',
}

def tracking(self):
return {
'statusDate': 'dateEtat',
'estDeliveryDate': 'dateLivraison',
'status': 'status',
'statusDetails': 'libelleLongEtat',
'trackingCode': 'noSuivi',
'publicUrl': 'urlSuiviDestinataire',
'proofUrl': 'urlImageEnlevementLivraison',
}

def schema(self):
return {
'parcels': self.parcels(),
'service': self.service(),
'from_address': self.from_address(),
'to_address': self.to_address(),
'tracking': self.tracking(),
}
88 changes: 8 additions & 80 deletions roulier/carriers/geodis/geodis_decoder_rest_ws.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
"""Geodis XML -> Python."""
from roulier.codec import Decoder

from .geodis_api_rest_ws import GeodisApiTrackingListOut

class GeodisDecoderRestWs(Decoder):
"""Geodis XML -> Python."""
Expand All @@ -13,91 +13,19 @@ def decode(self, payload, action):
"""
body = payload['body']
if action == 'trackingList':
mapping = GeodisTrackingListApi()
formatted = [
mapping.extract(line) for
line in body]
mapping = GeodisApiTrackingListOut()
formatted = []
for line in body:
self.add_tracking_code(line)
formatted.append(
mapping.normalize(line)
)
else:
# NOT implemented
formatted = body
return formatted


class GeodisTrackingListApi():

def to_address(self):
return {
'street1': 'adresse1Dest',
'street2': 'adresse2Dest',
'country': 'codePaysDest',
'zip': 'codePostalDest',
'country_name': 'libellePaysDest',
'name': 'nomDest',
'city': 'villeDest',
}

def from_address(self):
return {
'street1': 'adresse1Exp',
'street2': 'adresse2Exp',
'country': 'codePaysExp',
'zip': 'codePostalExp',
'country_name': 'libellePaysExp',
'name': 'nomExp',
'city': 'villeExp',
}

def parcels(self):
return {
'weight': 'poids',
}

def service(self):
return {
"product": 'codeProduit',
"agencyId": 'codeSa',
"customerId": 'codeClient',
"shippingId": 'noRecepisse',
'shippingDate': 'dateDepart',
'reference1': 'reference1',
'reference2': 'reference2',
'reference3': 'refDest',
'option': 'codeOption',
}

def tracking(self):
return {
'statusDate': 'dateEtat',
'estDeliveryDate': 'dateLivraison',
'status': 'status',
'statusDetails': 'libelleLongEtat',
'trackingCode': 'noSuivi',
'publicUrl': 'urlSuiviDestinataire',
'proofUrl': 'urlImageEnlevementLivraison',
}

def schema(self):
return {
'parcels': self.parcels(),
'service': self.service(),
'from_address': self.from_address(),
'to_address': self.to_address(),
'tracking': self.tracking(),
}

def extract(self, data):
schema = self.schema()
self.add_tracking_code(data)
return self.visit(data, schema)

def visit(self, data, schema):
out = {}
for (key, val) in schema.items():
if isinstance(val, dict):
out[key] = self.visit(data, val)
else:
out[key] = data[val]
return out

def add_tracking_code(self, data):
# MVL: mise en livraison
Expand Down
8 changes: 4 additions & 4 deletions roulier/carriers/geodis/geodis_transport_rest_ws.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,19 +84,19 @@ def handle_500(self, response):
}]
raise CarrierError(response, errors)

def handle_true_negative_error(self, response):
def handle_true_negative_error(self, response, payload):
"""When servers answer an error with a 200 status code."""
errors = [{
"id": response.get('codeErreur', ''),
"message": response.get('texteErreur', '')
"id": payload.get('codeErreur', ''),
"message": payload.get('texteErreur', '')
}]
raise CarrierError(response, errors)

def handle_200(self, response):
"""Handle response type 200."""
payload = json.loads(response.text)
if payload['ok'] is not True:
self.handle_true_negative_error(response)
self.handle_true_negative_error(response, payload)
return {
"body": payload.get('contenu', []),
"parts": [],
Expand Down
19 changes: 17 additions & 2 deletions roulier/carriers/geodis/tests/test_rest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,10 @@
import json
from collections import OrderedDict

from ..geodis_decoder_rest_ws import GeodisTrackingListApi, GeodisDecoderRestWs
from ..geodis_decoder_rest_ws import GeodisDecoderRestWs
from ..geodis_encoder_rest_ws import GeodisEncoderRestWs
from ..geodis_transport_rest_ws import GeodisTransportRestWs
from ..geodis_api_rest_ws import GeodisApiTrackingListOut


def test_encode():
Expand All @@ -17,6 +18,20 @@ def test_encode():
assert infos['service'] in infos['url']


def test_encode_api():
encoder = GeodisEncoderRestWs()
data = encoder.api('trackingList')

data['service']['shippingDateStart'] = "2019-07-02"
data['service']['shippingDateEnd'] = "2019-07-02"
data['auth']['login'] = 'Akretion'
data['auth']['password'] = '121221789271'

payload = encoder.encode(data, 'trackingList')
body = payload['body']
assert body['dateDepartFin'] == "2019-07-02"


def test_transport_hash():
"""Ensure we encode the has the same way as the specification
Expand Down Expand Up @@ -56,7 +71,7 @@ def test_transport_hash():


def test_decoder_visit():
api = GeodisTrackingListApi()
api = GeodisApiTrackingListOut()
schema = {
'str': 'simple_string',
'int': 'simple_integer',
Expand Down

0 comments on commit 3017395

Please sign in to comment.