2019-11-11 11:26:42 -06:00
|
|
|
# -*- 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
|
2019-11-11 12:36:50 -06:00
|
|
|
supports_toggle_complete = False
|
2019-11-11 11:26:42 -06:00
|
|
|
|
|
|
|
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
|
|
|
|
|
2019-11-11 12:36:50 -06:00
|
|
|
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)
|
|
|
|
|
2019-11-11 11:26:42 -06:00
|
|
|
@classmethod
|
|
|
|
def _batch_defaults(cls, config):
|
|
|
|
route_prefix = cls.get_route_prefix()
|
2019-11-11 12:36:50 -06:00
|
|
|
collection_url_prefix = cls.get_collection_url_prefix()
|
|
|
|
object_url_prefix = cls.get_object_url_prefix()
|
|
|
|
permission_prefix = cls.get_permission_prefix()
|
2019-11-11 11:26:42 -06:00
|
|
|
|
|
|
|
if cls.supports_quick_entry:
|
2019-11-11 12:36:50 -06:00
|
|
|
|
|
|
|
# quick entry
|
|
|
|
config.add_route('{}.quick_entry'.format(route_prefix), '{}/quick-entry'.format(collection_url_prefix),
|
2019-11-11 11:26:42 -06:00
|
|
|
request_method=('OPTIONS', 'POST'))
|
|
|
|
config.add_view(cls, attr='quick_entry', route_name='{}.quick_entry'.format(route_prefix),
|
2019-11-11 12:36:50 -06:00
|
|
|
permission='{}.edit'.format(permission_prefix),
|
2019-11-11 11:26:42 -06:00
|
|
|
renderer='json')
|
2019-11-11 12:36:50 -06:00
|
|
|
|
|
|
|
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')
|
|
|
|
|