Add support for label batch "quick entry" API
plus other general improvements to API core/master views and config
This commit is contained in:
parent
c520dc23ba
commit
bd09acd0fd
|
@ -25,3 +25,5 @@ Tailbone Web API - Batches
|
|||
"""
|
||||
|
||||
from __future__ import unicode_literals, absolute_import
|
||||
|
||||
from .core import BatchAPIMasterView
|
||||
|
|
108
tailbone/api/batch/core.py
Normal file
108
tailbone/api/batch/core.py
Normal file
|
@ -0,0 +1,108 @@
|
|||
# -*- coding: utf-8; -*-
|
||||
################################################################################
|
||||
#
|
||||
# Rattail -- Retail Software Framework
|
||||
# Copyright © 2010-2019 Lance Edgar
|
||||
#
|
||||
# This file is part of Rattail.
|
||||
#
|
||||
# Rattail is free software: you can redistribute it and/or modify it under the
|
||||
# terms of the GNU General Public License as published by the Free Software
|
||||
# Foundation, either version 3 of the License, or (at your option) any later
|
||||
# version.
|
||||
#
|
||||
# Rattail is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License along with
|
||||
# Rattail. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
################################################################################
|
||||
"""
|
||||
Tailbone Web API - Batch Views
|
||||
"""
|
||||
|
||||
from __future__ import unicode_literals, absolute_import
|
||||
|
||||
import six
|
||||
|
||||
from rattail.util import load_object
|
||||
|
||||
from tailbone.api import APIMasterView
|
||||
|
||||
|
||||
class BatchAPIMasterView(APIMasterView):
|
||||
"""
|
||||
Base class for all API views which are meant to handle "batch" *and/or*
|
||||
"batch row" data.
|
||||
"""
|
||||
supports_quick_entry = False
|
||||
|
||||
def __init__(self, request, **kwargs):
|
||||
super(BatchAPIMasterView, self).__init__(request, **kwargs)
|
||||
self.handler = self.get_handler()
|
||||
|
||||
@classmethod
|
||||
def get_batch_class(cls):
|
||||
model_class = cls.get_model_class()
|
||||
if hasattr(model_class, '__batch_class__'):
|
||||
return model_class.__batch_class__
|
||||
return model_class
|
||||
|
||||
def get_handler(self):
|
||||
"""
|
||||
Returns a `BatchHandler` instance for the view. All (?) custom batch
|
||||
API views should define a default handler class; however this may in all
|
||||
(?) cases be overridden by config also. The specific setting required
|
||||
to do so will depend on the 'key' for the type of batch involved, e.g.
|
||||
assuming the 'vendor_catalog' batch:
|
||||
|
||||
.. code-block:: ini
|
||||
|
||||
[rattail.batch]
|
||||
vendor_catalog.handler = myapp.batch.vendorcatalog:CustomCatalogHandler
|
||||
|
||||
Note that the 'key' for a batch is generally the same as its primary
|
||||
table name, although technically it is whatever value returns from the
|
||||
``batch_key`` attribute of the main batch model class.
|
||||
"""
|
||||
key = self.get_batch_class().batch_key
|
||||
spec = self.rattail_config.get('rattail.batch', '{}.handler'.format(key),
|
||||
default=self.default_handler_spec)
|
||||
return load_object(spec)(self.rattail_config)
|
||||
|
||||
def quick_entry(self):
|
||||
"""
|
||||
View for handling "quick entry" user input, for a batch.
|
||||
"""
|
||||
data = self.request.json_body
|
||||
|
||||
uuid = data['batch_uuid']
|
||||
batch = self.Session.query(self.get_batch_class()).get(uuid)
|
||||
if not batch:
|
||||
raise self.notfound()
|
||||
|
||||
entry = data['quick_entry']
|
||||
|
||||
try:
|
||||
row = self.handler.quick_entry(self.Session(), batch, entry)
|
||||
except Exception as error:
|
||||
return {'error': six.text_type(error)}
|
||||
|
||||
result = self._get(obj=row)
|
||||
result['ok'] = True
|
||||
return result
|
||||
|
||||
@classmethod
|
||||
def _batch_defaults(cls, config):
|
||||
route_prefix = cls.get_route_prefix()
|
||||
url_prefix = cls.get_url_prefix()
|
||||
|
||||
# quick entry
|
||||
if cls.supports_quick_entry:
|
||||
config.add_route('{}.quick_entry'.format(route_prefix), '{}/quick-entry'.format(url_prefix),
|
||||
request_method=('OPTIONS', 'POST'))
|
||||
config.add_view(cls, attr='quick_entry', route_name='{}.quick_entry'.format(route_prefix),
|
||||
renderer='json')
|
|
@ -34,6 +34,7 @@ from rattail.time import localtime
|
|||
from cornice import resource
|
||||
|
||||
from tailbone.api import APIMasterView
|
||||
from tailbone.api.batch import BatchAPIMasterView
|
||||
|
||||
|
||||
class LabelBatchViews(APIMasterView):
|
||||
|
@ -107,9 +108,14 @@ class LabelBatchViews(APIMasterView):
|
|||
config.add_cornice_resource(batch_resource)
|
||||
|
||||
|
||||
class LabelBatchRowViews(APIMasterView):
|
||||
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'
|
||||
|
||||
def normalize(self, row):
|
||||
batch = row.batch
|
||||
|
@ -124,7 +130,10 @@ class LabelBatchRowViews(APIMasterView):
|
|||
'batch_description': batch.description,
|
||||
'sequence': row.sequence,
|
||||
'item_id': row.item_id,
|
||||
'upc': six.text_type(row.upc),
|
||||
'upc_pretty': row.upc.pretty() if row.upc else None,
|
||||
'description': row.description,
|
||||
'full_description': row.product.full_description if row.product else row.description,
|
||||
'status_code': row.status_code,
|
||||
'status_display': row.STATUS.get(row.status_code, six.text_type(row.status_code)),
|
||||
}
|
||||
|
@ -137,13 +146,16 @@ class LabelBatchRowViews(APIMasterView):
|
|||
|
||||
@classmethod
|
||||
def defaults(cls, config):
|
||||
permission_prefix = cls.get_permission_prefix()
|
||||
|
||||
# label batch rows
|
||||
resource.add_view(cls.collection_get, permission='labels.batch.view')
|
||||
resource.add_view(cls.get, permission='labels.batch.view')
|
||||
resource.add_view(cls.collection_get, permission='{}.view'.format(permission_prefix))
|
||||
resource.add_view(cls.get, permission='{}.view'.format(permission_prefix))
|
||||
rows_resource = resource.add_resource(cls, collection_path='/label-batch-rows', path='/label-batch-row/{uuid}')
|
||||
config.add_cornice_resource(rows_resource)
|
||||
|
||||
cls._batch_defaults(config)
|
||||
|
||||
|
||||
def includeme(config):
|
||||
LabelBatchViews.defaults(config)
|
||||
|
|
|
@ -62,6 +62,40 @@ class APIMasterView(APIView):
|
|||
return cls.normalized_model_name
|
||||
return cls.get_model_class().__name__.lower()
|
||||
|
||||
@classmethod
|
||||
def get_route_prefix(cls):
|
||||
"""
|
||||
Returns a prefix which (by default) applies to all routes provided by
|
||||
this view class.
|
||||
"""
|
||||
prefix = getattr(cls, 'route_prefix', None)
|
||||
if prefix:
|
||||
return prefix
|
||||
model_name = cls.get_normalized_model_name()
|
||||
return 'api.{}s'.format(model_name)
|
||||
|
||||
@classmethod
|
||||
def get_permission_prefix(cls):
|
||||
"""
|
||||
Returns a prefix which (by default) applies to all permissions
|
||||
leveraged by this view class.
|
||||
"""
|
||||
prefix = getattr(cls, 'permission_prefix')
|
||||
if prefix:
|
||||
return prefix
|
||||
return cls.get_route_prefix()
|
||||
|
||||
@classmethod
|
||||
def get_url_prefix(cls):
|
||||
"""
|
||||
Returns a prefix which (by default) applies to all URLs provided by
|
||||
this view class.
|
||||
"""
|
||||
prefix = getattr(cls, 'url_prefix', None)
|
||||
if prefix:
|
||||
return prefix
|
||||
return '/{}'.format(cls.get_route_prefix())
|
||||
|
||||
@classmethod
|
||||
def get_object_key(cls):
|
||||
if hasattr(cls, 'object_key'):
|
||||
|
|
Loading…
Reference in a new issue