From f4e4469e70d8f3dcefd3b0ea3c007863785f8164 Mon Sep 17 00:00:00 2001 From: Lucidiot Date: Sun, 3 Feb 2019 19:07:01 +0100 Subject: [PATCH] Add Item, LogEntry, and more attributes --- urbantz/delivery.py | 65 +++++++++++++++++++++- urbantz/items.py | 132 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 194 insertions(+), 3 deletions(-) create mode 100644 urbantz/items.py diff --git a/urbantz/delivery.py b/urbantz/delivery.py index 0848b44..d719354 100644 --- a/urbantz/delivery.py +++ b/urbantz/delivery.py @@ -1,9 +1,12 @@ from datetime import datetime, timedelta from urbantz.base import JSONSerializable, Coordinates from urbantz.utils import DictObject +from urbantz.items import LogEntry, Item from urbantz.exceptions import APIError import requests +DATE_FORMAT = '%Y-%m-%dT%H:%M:%S.%fZ' + class Delivery(JSONSerializable): """ @@ -59,6 +62,27 @@ class Delivery(JSONSerializable): :type: str or None """ + self.platform_id = None + """ + Platform identifier for this delivery. + + :type: str or None + """ + + self.driver_id = None + """ + Driver identifier for this delivery. + + :type: str or None + """ + + self.round_id = None + """ + Driver round identifier for this delivery. + + :type: str or None + """ + self.instructions = None """ Delivery instructions given to the driver. @@ -66,6 +90,20 @@ class Delivery(JSONSerializable): :type: str or None """ + self.progress = None + """ + The delivery order progress. + + :type: str or None + """ + + self.status = None + """ + The delivery status. + + :type: str or None + """ + self.arrival_time = None """ Estimated or actual arrival time. @@ -127,6 +165,20 @@ class Delivery(JSONSerializable): :type: urbantz.utils.DictObject or None """ + self.items = None + """ + List of delivery items. + + :type: list(urbantz.items.Item) + """ + + self.logs = None + """ + List of status update logs for the delivery. + + :type: list(urbantz.items.LogEntry) + """ + def __repr__(self): return '{}({})'.format( self.__class__.__name__, repr(self.tracking_code)) @@ -200,21 +252,26 @@ class Delivery(JSONSerializable): self.date = datetime.strptime( self.payload['date'][:10], "%Y-%m-%d").date() self.task_id = self.payload['taskId'] + self.platform_id = self.payload['platform'] + self.driver_id = self.payload['driver'] + self.round_id = self.payload['round'] self.by = self.payload['by'] self.instructions = self.payload['instructions'] + self.progress = self.payload['progress'] + self.status = self.payload['status'] self.arrival_time = datetime.strptime( - self.payload['arriveTime'], '%Y-%m-%dT%H:%M:%S.000Z') + self.payload['arriveTime'], DATE_FORMAT) 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', + DATE_FORMAT, ), datetime.strptime( self.payload['timeWindow']['stop'], - '%Y-%m-%dT%H:%M:%S.000Z', + DATE_FORMAT, ), ] @@ -223,6 +280,8 @@ class Delivery(JSONSerializable): self.payload['location']['location']['geometry']) self.recipient = DictObject(self.payload['contact']) self.features = DictObject(self.payload['features']) + self.logs = list(map(LogEntry.fromJSON, self.payload['log'])) + self.items = list(map(Item.fromJSON, self.payload['items'])) @classmethod def fromJSON(cls, payload): diff --git a/urbantz/items.py b/urbantz/items.py new file mode 100644 index 0000000..2919f3a --- /dev/null +++ b/urbantz/items.py @@ -0,0 +1,132 @@ +from datetime import datetime +from urbantz.base import JSONSerializable +from urbantz.utils import DictObject + + +class LogEntry(DictObject): + """ + A log entry for a delivery or a delivery item that logs status changes. + + - ``id`` : Unique identifier of the log entry + - ``by`` : Unique identifier of the author of the change. Nullable. + - ``when`` : Date/time of the log entry as a ISO 8601 string + - ``to`` : Updated status + """ + + @property + def datetime(self): + """ + Datetime for the log entry. + """ + from urbantz.delivery import DATE_FORMAT + return datetime.strptime(self.when, DATE_FORMAT) + + +class Item(JSONSerializable): + """ + Describes a delivery item. + """ + + def __init__(self, payload): + self.payload = payload + """ + The original JSON payload for the item. + + :type: dict + """ + + self.id = self.payload['_id'] + """ + Unique identifier of the delivery item. + + :type: str + """ + + self.type = self.payload['type'] + """ + Type of the delivery item. Types vary with each company. + + :type: str + """ + + self.barcode = self.payload['barcode'] + """ + Barcode of the delivery item. See :attr:`Item.barcode_encoding` to + know the barcode's encoding. + """ + + self.barcode_encoding = self.payload['barcodeEncoding'] + """ + Encoding method of the barcode (EAN 13, UPC, etc.) + """ + + self.damage_confirmed = self.payload['damaged']['confirmed'] + """ + Indicates whether the item has been damaged. + + :type: bool + """ + + self.damage_pictures = self.payload['damaged']['pictures'] + """ + Pictures of the damages. + """ + + self.status = self.payload['status'] + """ + Status of the delivery item. + + :type: str + """ + + self.quantity = self.payload['quantity'] + """ + Quantity of the given item. + + :type: int + """ + + self.labels = self.payload['labels'] + """ + Custom labels given to the item. + + :type: list + """ + + self.skills = self.payload['skills'] + """ + Required skills to handle the delivery item. + + :type: list + """ + + self.dimensions = DictObject(self.payload['dimensions']) + """ + Dimensions of the item, as custom settings set by the shipment company. + + :type: urbantz.utils.DictObject + """ + + self.metadata = DictObject(self.payload['metadata']) + """ + Metadata about the delivery that seems to be set by UrbanTZ themselves. + + :type: urbantz.utils.DictObject + """ + + self.logs = list(map(LogEntry.fromJSON, self.payload['log'])) + """ + Status update logs. + + :type: urbantz.items.LogEntry + """ + + def __repr__(self): + return ''.format(self.id) + + def toJSON(self): + return self.payload + + @classmethod + def fromJSON(cls, payload): + return cls(payload)