diff --git a/python/delivery_controller.py b/python/delivery_controller.py
index a829e54..e5fb6f2 100644
--- a/python/delivery_controller.py
+++ b/python/delivery_controller.py
@@ -23,16 +23,42 @@ class Delivery:
on_time: bool
+class Notifier:
+
+ def request_feedback(self, delivery: Delivery):
+ raise NotImplemented()
+
+ def send_eta_update(self, delivery: Delivery, new_eta: int):
+ raise NotImplemented()
+
+class SmtpNotifier:
+
+ def __init__(self, gateway: EmailGateway):
+ self.gateway = gateway
+
+ def request_feedback(self, delivery: Delivery):
+ message = f"""Regarding your delivery today at {delivery.time_of_delivery}. How likely would you be to recommend this delivery service to a friend? Click here"""
+ self.gateway.send(
+ delivery.contact_email, "Your feedback is important to us", message
+ )
+
+ def send_eta_update(self, delivery: Delivery, new_eta: int):
+ message = f"Your delivery to {delivery.location} is next, estimated time of arrival is in {new_eta} minutes. Be ready!"
+ self.gateway.send(
+ delivery.contact_email, "Your delivery will arrive soon", message
+ )
+
+
class DeliveryController:
def __init__(
self,
delivery_schedule: List[Delivery],
- gateway: Optional[EmailGateway],
+ notifier: Optional[Notifier] = None,
maps: Optional[MapService] = None,
):
self.delivery_schedule = delivery_schedule
- self.email_gateway = gateway or EmailGateway()
self.map_service = maps or MapService()
+ self.notifier = notifier or SmtpNotifier(EmailGateway())
def update_delivery(self, delivery_event: DeliveryEvent):
next_delivery = None
@@ -45,10 +71,8 @@ def update_delivery(self, delivery_event: DeliveryEvent):
if time_difference < datetime.timedelta(minutes=10):
delivery.on_time = True
delivery.time_of_delivery = delivery_event.time_of_delivery
- message = f"""Regarding your delivery today at {delivery.time_of_delivery}. How likely would you be to recommend this delivery service to a friend? Click here"""
- self.email_gateway.send(
- delivery.contact_email, "Your feedback is important to us", message
- )
+ self.notifier.request_feedback(delivery)
+
if len(self.delivery_schedule) > i + 1:
next_delivery = self.delivery_schedule[i + 1]
if not delivery.on_time and len(self.delivery_schedule) > 1 and i > 0:
@@ -63,7 +87,4 @@ def update_delivery(self, delivery_event: DeliveryEvent):
next_eta = self.map_service.calculate_eta(
delivery_event.location, next_delivery.location
)
- message = f"Your delivery to {next_delivery.location} is next, estimated time of arrival is in {next_eta} minutes. Be ready!"
- self.email_gateway.send(
- next_delivery.contact_email, "Your delivery will arrive soon", message
- )
+ self.notifier.send_eta_update(next_delivery, next_eta)
diff --git a/python/test_delivery_service.py b/python/test_delivery_service.py
index 4c77e47..6cb2c86 100644
--- a/python/test_delivery_service.py
+++ b/python/test_delivery_service.py
@@ -1,13 +1,16 @@
import pytest
import datetime
-from delivery_controller import DeliveryController, Delivery, DeliveryEvent
+from delivery_controller import DeliveryController, Delivery, DeliveryEvent, SmtpNotifier
from map_service import MapService, Location
location1 = Location(52.2296756, 21.0122287)
location2 = Location(52.406374, 16.9251681)
location3 = Location(51.406374, 17.9251681)
+now = datetime.datetime.now()
+one_hour = datetime.timedelta(hours=1)
+
def test_map_service():
map_service = MapService()
@@ -48,7 +51,7 @@ def a_delivery(
id=id,
contact_email="fred@codefiend.co.uk",
location=location,
- time_of_delivery=time or datetime.datetime.now,
+ time_of_delivery=time or now,
arrived=False,
on_time=False,
)
@@ -56,22 +59,11 @@ def a_delivery(
def test_a_single_delivery_is_delivered():
- now = datetime.datetime.now()
-
- delivery = Delivery(
- id=1,
- contact_email="fred@codefiend.co.uk",
- location=location1,
- time_of_delivery=now,
- arrived=False,
- on_time=True,
- )
-
- update = DeliveryEvent(1, now, location2)
+ delivery = a_delivery(1)
gateway = FakeEmailGateway()
- controller = DeliveryController([delivery], gateway)
+ controller = DeliveryController([delivery], SmtpNotifier(gateway))
- controller.update_delivery(update)
+ controller.update_delivery(DeliveryEvent(1, now, location2))
assert delivery.arrived is True
assert delivery.on_time is True
@@ -87,11 +79,19 @@ def test_a_single_delivery_is_delivered():
)
-now = datetime.datetime.now()
-one_hour = datetime.timedelta(hours=1)
-
def test_when_a_delivery_affects_the_schedule():
+ """
+ In this scenario, we have three deliveries to three locations.
+ The first is scheduled to happen now, the second in an hour, the third in
+ two hours.
+
+ When the second delivery is delivered an hour late, we should call the map
+ service to recalculate our average speed.
+
+ We should send an email to the recipient of delivery 3 with the updated
+ ETA.
+ """
deliveries = [
a_delivery(1, time=now, location=location1),
@@ -100,8 +100,8 @@ def test_when_a_delivery_affects_the_schedule():
]
gateway = FakeEmailGateway()
- maps = FakeMapService(10)
- controller = DeliveryController(deliveries, gateway, maps)
+ maps = FakeMapService(325)
+ controller = DeliveryController(deliveries, SmtpNotifier(gateway), maps)
controller.update_delivery(DeliveryEvent(2, now + (one_hour * 2), location2))
@@ -110,3 +110,8 @@ def test_when_a_delivery_affects_the_schedule():
assert start == location1
assert end == location2
assert time == (one_hour * 2)
+
+ [_,(address, subject, message)] = gateway.sent
+
+ assert subject == "Your delivery will arrive soon"
+ assert message == f"Your delivery to {location3} is next, estimated time of arrival is in 325 minutes. Be ready!"