From afdd294c6037cda93dae1147157f85f5a7c8f754 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Mon, 11 Nov 2019 12:36:50 -0600 Subject: [PATCH] Add support for "toggle complete" for batch API --- tailbone/api/batch/core.py | 60 ++++++++++++++++++++++++++++++++++-- tailbone/api/batch/labels.py | 13 +++++--- tailbone/api/master.py | 35 +++++++++++++++------ 3 files changed, 92 insertions(+), 16 deletions(-) diff --git a/tailbone/api/batch/core.py b/tailbone/api/batch/core.py index 55d1baeb..8e6af1e9 100644 --- a/tailbone/api/batch/core.py +++ b/tailbone/api/batch/core.py @@ -39,6 +39,7 @@ class BatchAPIMasterView(APIMasterView): "batch row" data. """ supports_quick_entry = False + supports_toggle_complete = False def __init__(self, request, **kwargs): super(BatchAPIMasterView, self).__init__(request, **kwargs) @@ -95,14 +96,67 @@ class BatchAPIMasterView(APIMasterView): result['ok'] = True return result + def mark_complete(self): + """ + Mark the given batch as "complete". + """ + batch = self.get_object() + + if batch.executed: + return {'error': "Batch {} has already been executed: {}".format( + batch.id_str, batch.description)} + + if batch.complete: + return {'error': "Batch {} is already marked complete: {}".format( + batch.id_str, batch.description)} + + batch.complete = True + return self._get(obj=batch) + + def mark_incomplete(self): + """ + Mark the given batch as "incomplete". + """ + batch = self.get_object() + + if batch.executed: + return {'error': "Batch {} has already been executed: {}".format( + batch.id_str, batch.description)} + + if not batch.complete: + return {'error': "Batch {} is already marked incomplete: {}".format( + batch.id_str, batch.description)} + + batch.complete = False + return self._get(obj=batch) + @classmethod def _batch_defaults(cls, config): route_prefix = cls.get_route_prefix() - url_prefix = cls.get_url_prefix() + collection_url_prefix = cls.get_collection_url_prefix() + object_url_prefix = cls.get_object_url_prefix() + permission_prefix = cls.get_permission_prefix() - # quick entry if cls.supports_quick_entry: - config.add_route('{}.quick_entry'.format(route_prefix), '{}/quick-entry'.format(url_prefix), + + # quick entry + config.add_route('{}.quick_entry'.format(route_prefix), '{}/quick-entry'.format(collection_url_prefix), request_method=('OPTIONS', 'POST')) config.add_view(cls, attr='quick_entry', route_name='{}.quick_entry'.format(route_prefix), + permission='{}.edit'.format(permission_prefix), renderer='json') + + if cls.supports_toggle_complete: + + # mark complete + config.add_route('{}.mark_complete'.format(route_prefix), '{}/{{uuid}}/mark-complete'.format(object_url_prefix)) + config.add_view(cls, attr='mark_complete', route_name='{}.mark_complete'.format(route_prefix), + permission='{}.edit'.format(permission_prefix), + renderer='json') + + # mark incomplete + config.add_route('{}.mark_incomplete'.format(route_prefix), '{}/{{uuid}}/mark-incomplete'.format(object_url_prefix)) + config.add_view(cls, attr='mark_incomplete', route_name='{}.mark_incomplete'.format(route_prefix), + permission='{}.edit'.format(permission_prefix), + renderer='json') + diff --git a/tailbone/api/batch/labels.py b/tailbone/api/batch/labels.py index b18a733b..05553c5a 100644 --- a/tailbone/api/batch/labels.py +++ b/tailbone/api/batch/labels.py @@ -33,13 +33,16 @@ from rattail.time import localtime from cornice import resource -from tailbone.api import APIMasterView from tailbone.api.batch import BatchAPIMasterView -class LabelBatchViews(APIMasterView): +class LabelBatchViews(BatchAPIMasterView): model_class = model.LabelBatch + default_handler_spec = 'rattail.batch.labels:LabelBatchHandler' + permission_prefix = 'labels.batch' + object_url_prefix = '/label-batch' + supports_toggle_complete = True def pretty_datetime(self, dt): if not dt: @@ -107,15 +110,17 @@ class LabelBatchViews(APIMasterView): batch_resource = resource.add_resource(cls, collection_path='/label-batches', path='/label-batch/{uuid}') config.add_cornice_resource(batch_resource) + cls._batch_defaults(config) + class LabelBatchRowViews(BatchAPIMasterView): model_class = model.LabelBatchRow default_handler_spec = 'rattail.batch.labels:LabelBatchHandler' - supports_quick_entry = True route_prefix = 'api.label_batch_rows' permission_prefix = 'labels.batch' - url_prefix = '/label-batch-rows' + collection_url_prefix = '/label-batch-rows' + supports_quick_entry = True def normalize(self, row): batch = row.batch diff --git a/tailbone/api/master.py b/tailbone/api/master.py index 1c3a0d08..cec37b77 100644 --- a/tailbone/api/master.py +++ b/tailbone/api/master.py @@ -86,12 +86,23 @@ class APIMasterView(APIView): return cls.get_route_prefix() @classmethod - def get_url_prefix(cls): + def get_collection_url_prefix(cls): """ - Returns a prefix which (by default) applies to all URLs provided by - this view class. + Returns a prefix which (by default) applies to all "collection" URLs + provided by this view class. """ - prefix = getattr(cls, 'url_prefix', None) + prefix = getattr(cls, 'collection_url_prefix', None) + if prefix: + return prefix + return '/{}'.format(cls.get_route_prefix()) + + @classmethod + def get_object_url_prefix(cls): + """ + Returns a prefix which (by default) applies to all "object" URLs + provided by this view class. + """ + prefix = getattr(cls, 'object_url_prefix', None) if prefix: return prefix return '/{}'.format(cls.get_route_prefix()) @@ -271,13 +282,19 @@ class APIMasterView(APIView): return context + def get_object(self, uuid=None): + if not uuid: + uuid = self.request.matchdict['uuid'] + + obj = self.Session.query(self.get_model_class()).get(uuid) + if obj: + return obj + + raise self.notfound() + def _get(self, obj=None, uuid=None): if not obj: - if not uuid: - uuid = self.request.matchdict['uuid'] - obj = self.Session.query(self.get_model_class()).get(uuid) - if not obj: - raise self.notfound() + obj = self.get_object(uuid=uuid) key = self.get_object_key() normal = self.normalize(obj) return {key: normal, 'data': normal}