diff --git a/urbantz/delivery.py b/urbantz/delivery.py index 467d761..cbf5f4f 100644 --- a/urbantz/delivery.py +++ b/urbantz/delivery.py @@ -1,6 +1,7 @@ from datetime import datetime from urbantz.utils import Coordinates from urbantz.exceptions import APIError +import json import requests @@ -9,15 +10,16 @@ class Delivery(object): A UrbanTZ delivery with a unique ID. """ - def __init__(self, id): + def __init__(self, tracking_code=None): """ - :param str id: A delivery ID. + :param tracking_code: A delivery public tracking code. + :type tracking_code: str or None """ - self.id = id + self.tracking_code = tracking_code """ - The delivery ID. + The delivery public tracking code. - :type: str + :type: str or None """ self.last_updated = None @@ -28,6 +30,14 @@ class Delivery(object): :type: datetime or None """ + self.payload = None + """ + Latest parsed JSON payload from the API. Is None if data has never + been fetched from the API or loaded via :meth:`Delivery.use`. + + :type: dict or None + """ + self.position = None """ Coordinates of the delivery truck's position. @@ -43,7 +53,7 @@ class Delivery(object): """ def __repr__(self): - return '{}({})'.format(self.__class__.__name__, self.id) + return '{}({})'.format(self.__class__.__name__, repr(self.tracking_code)) @property def api_url(self): @@ -52,7 +62,7 @@ class Delivery(object): :type: str """ - return 'https://backend.urbantz.com/public/task/tracking/' + self.id + return 'https://backend.urbantz.com/public/task/tracking/' + self.tracking_code def update(self): """ @@ -67,10 +77,37 @@ class Delivery(object): data = resp.json() if 'error' in data: - raise APIError(data['error']) + raise APIError(self.payload['error']) - self.position = Coordinates.fromJSON(data['position']) - self.destination = Coordinates.fromJSON( - data['location']['location']['geometry']) + self.use(data) + # TODO: See if the payload holds a last update value self.last_updated = datetime.now() + + def use(self, payload): + """ + Use a parsed JSON payload to update the properties. + + :param dict payload: A parsed JSON payload from the API. + """ + self.payload = payload + self.position = Coordinates.fromJSON(self.payload['position']) + self.destination = Coordinates.fromJSON( + self.payload['location']['location']['geometry']) + + @classmethod + def from_payload(cls, payload): + """ + Create a Delivery instance from an existing payload. + + :param payload: A parsed JSON payload, a str holding a JSON payload, + or an open file-like object. + :type payload: dict or str or file-like object + """ + if isinstance(payload, str): + payload = json.loads(payload) + if not isinstance(payload, dict): + payload = json.load(payload) + instance = cls() + instance.use(payload) + return instance