Use a ModelList for lists of jobs

This follows the pattern of what we’ve done with services, users and
events.

It gives us a way of neatly instantiating a model for each item in the
list we get back from the API and reduces the complexity of the view
layer code.

Now is a good time to do this because we’re going to be making a bunch
of changes to the jobs pages, and those changes will be easier to code
and understand with a sensible model behind them.
This commit is contained in:
Chris Hill-Scott
2020-01-08 14:29:56 +00:00
parent 5e7ec3e30d
commit 25464a141b
13 changed files with 106 additions and 76 deletions

View File

@@ -7,7 +7,7 @@ from notifications_utils.letter_timings import (
)
from werkzeug.utils import cached_property
from app.models import JSONModel
from app.models import JSONModel, ModelList
from app.notify_client.job_api_client import job_api_client
from app.notify_client.notification_api_client import notification_api_client
from app.notify_client.service_api_client import service_api_client
@@ -147,6 +147,20 @@ class Job(JSONModel):
def letter_timings(self):
return get_letter_timings(self.created_at, postage=self.postage)
@property
def failure_rate(self):
if not self.notifications_delivered:
return 100 if self.notifications_failed else 0
return (
self.notifications_failed / (
self.notifications_failed + self.notifications_delivered
) * 100
)
@property
def high_failure_rate(self):
return self.failure_rate > 30
def get_notifications(self, status):
return notification_api_client.get_notifications_for_service(
self.service, self.id, status=status,
@@ -157,3 +171,31 @@ class Job(JSONModel):
return job_api_client.cancel_letter_job(self.service, self.id)
else:
return job_api_client.cancel_job(self.service, self.id)
class ImmediateJobs(ModelList):
client = job_api_client.get_immediate_jobs
model = Job
class ScheduledJobs(ImmediateJobs):
client = job_api_client.get_scheduled_jobs
class PaginatedJobs(ImmediateJobs):
client = job_api_client.get_page_of_jobs
def __init__(self, service_id, page):
try:
self.current_page = int(page)
except TypeError:
self.current_page = 1
response = self.client(service_id, page=self.current_page)
self.items = response['data']
self.prev_page = response['links'].get('prev', None)
self.next_page = response['links'].get('next', None)
class PaginatedUploads(PaginatedJobs):
client = job_api_client.get_uploads

View File

@@ -5,6 +5,12 @@ from notifications_utils.take import Take
from werkzeug.utils import cached_property
from app.models import JSONModel
from app.models.job import (
ImmediateJobs,
PaginatedJobs,
PaginatedUploads,
ScheduledJobs,
)
from app.models.organisation import Organisation
from app.models.user import InvitedUsers, User, Users
from app.notify_client.api_key_api_client import api_key_api_client
@@ -103,10 +109,28 @@ class Service(JSONModel):
def has_permission(self, permission):
return permission in self.permissions
def get_page_of_jobs(self, page):
return PaginatedJobs(self.id, page=page)
def get_page_of_uploads(self, page):
return PaginatedUploads(self.id, page=page)
@cached_property
def has_jobs(self):
return job_api_client.has_jobs(self.id)
@cached_property
def immediate_jobs(self):
if not self.has_jobs:
return []
return ImmediateJobs(self.id)
@cached_property
def scheduled_jobs(self):
if not self.has_jobs:
return []
return ScheduledJobs(self.id)
@cached_property
def invited_users(self):
return InvitedUsers(self.id)