diff --git a/urbantz/delivery.py b/urbantz/delivery.py index 953236a..0848b44 100644 --- a/urbantz/delivery.py +++ b/urbantz/delivery.py @@ -1,4 +1,4 @@ -from datetime import datetime +from datetime import datetime, timedelta from urbantz.base import JSONSerializable, Coordinates from urbantz.utils import DictObject from urbantz.exceptions import APIError @@ -38,18 +38,74 @@ class Delivery(JSONSerializable): :type: dict or None """ + self.id = None + """ + Identifier for this delivery. + + :type: str or None + """ + + self.date = None + """ + Date of the delivery. + + :type: date or None + """ + + self.task_id = None + """ + Task identifier for this delivery. + + :type: str or None + """ + + self.instructions = None + """ + Delivery instructions given to the driver. + + :type: str or None + """ + + self.arrival_time = None + """ + Estimated or actual arrival time. + + :type: datetime or None + """ + + self.eta_margin = None + """ + Margin, in minutes, for the estimated time of arrival. + + :type: int or None + """ + + self.eta_rounding = None + """ + Rounding, in minutes, for the estimated time of arrival. + + :type: int or None + """ + + self.time_window = None + """ + Planned delivery time window (start and end datetimes) + + :type: list(datetime) or None + """ + self.position = None """ Coordinates of the delivery truck's position. - :type: urbantz.base.Coordinates + :type: urbantz.base.Coordinates or None """ self.destination = None """ Coordinates of the delivery destination. - :type: urbantz.base.Coordinates + :type: urbantz.base.Coordinates or None """ self.recipient = None @@ -57,7 +113,7 @@ class Delivery(JSONSerializable): Informations about the recipient (name, language, phone number, etc.) Does not contain the destination location information. - :type: urbantz.utils.DictObject + :type: urbantz.utils.DictObject or None """ self.features = None @@ -68,7 +124,7 @@ class Delivery(JSONSerializable): the client is allowed to update the delivery instructions after the driver departs for its round. - :type: urbantz.utils.DictObject + :type: urbantz.utils.DictObject or None """ def __repr__(self): @@ -85,6 +141,25 @@ class Delivery(JSONSerializable): return 'https://backend.urbantz.com/public/task/tracking/{}'.format( self.tracking_code) + @property + def eta(self): + """ + Estimated time of arrival: start and end datetimes, computed from the + arrival time and rounding settings + + :type: list(datetime) or None + """ + if not (self.eta_margin and self.eta_rounding and self.arrival_time): + return + start = self.arrival_time - timedelta(minutes=self.eta_margin / 2) + start -= timedelta( + minutes=start.minute % self.eta_rounding, + seconds=start.second, + microseconds=start.microsecond, + ) + end = start + timedelta(minutes=self.eta_margin) + return [start, end] + def update(self): """ Fetch the latest delivery information from the API. @@ -121,6 +196,28 @@ class Delivery(JSONSerializable): :param dict payload: A parsed JSON payload from the API. """ self.payload = payload + self.id = self.payload['_id'] + self.date = datetime.strptime( + self.payload['date'][:10], "%Y-%m-%d").date() + self.task_id = self.payload['taskId'] + self.by = self.payload['by'] + self.instructions = self.payload['instructions'] + + self.arrival_time = datetime.strptime( + self.payload['arriveTime'], '%Y-%m-%dT%H:%M:%S.000Z') + self.eta_margin = self.payload['eta']['margin'] + self.eta_rounding = self.payload['eta']['rounding'] + self.time_window = [ + datetime.strptime( + self.payload['timeWindow']['start'], + '%Y-%m-%dT%H:%M:%S.000Z', + ), + datetime.strptime( + self.payload['timeWindow']['stop'], + '%Y-%m-%dT%H:%M:%S.000Z', + ), + ] + self.position = Coordinates.fromJSON(self.payload['position']) self.destination = Coordinates.fromJSON( self.payload['location']['location']['geometry'])