Let inventory batch handler declare which count modes are allowed

preparing for API/mobile usage
This commit is contained in:
Lance Edgar 2020-03-29 12:46:41 -05:00
parent 242e14e8a9
commit 0704717ec5
2 changed files with 37 additions and 23 deletions

View file

@ -71,6 +71,7 @@ class BatchMasterView(MasterView):
Base class for all "batch master" views.
"""
default_handler_spec = None
batch_handler_class = None
has_rows = True
rows_deletable = True
rows_downloadable_csv = True
@ -120,29 +121,43 @@ class BatchMasterView(MasterView):
super(BatchMasterView, self).__init__(request)
self.handler = self.get_handler()
def get_handler(self):
@classmethod
def get_handler_factory(cls, rattail_config):
"""
Returns a `BatchHandler` instance for the view. All (?) custom batch
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:
Returns the "factory" (class) which will be used to create the batch
handler. All (?) custom batch 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 'inventory' batch:
.. code-block:: ini
[rattail.batch]
vendor_catalog.handler = myapp.batch.vendorcatalog:CustomCatalogHandler
inventory.handler = poser.batch.inventory:InventoryBatchHandler
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.model_class.batch_key
spec = self.rattail_config.get('rattail.batch', '{}.handler'.format(key),
default=self.default_handler_spec)
if spec:
return load_object(spec)(self.rattail_config)
return self.batch_handler_class(self.rattail_config)
# first try to figure out if config defines a factory class
model_class = cls.get_model_class()
batch_key = model_class.batch_key
spec = rattail_config.get('rattail.batch', '{}.handler'.format(batch_key),
default=cls.default_handler_spec)
if spec: # yep, so use that
return load_object(spec)
# fall back to whatever class was defined statically
return cls.batch_handler_class
def get_handler(self):
"""
Returns a batch handler instance to be used by the view. Note that
this will use the factory provided by :meth:`get_handler_factory()` to
create the handler instance.
"""
factory = self.get_handler_factory(self.rattail_config)
return factory(self.rattail_config)
def download_path(self, batch, filename):
return self.rattail_config.batch_filepath(batch.batch_key, batch.uuid, filename)

View file

@ -67,12 +67,6 @@ class InventoryBatchView(BatchMasterView):
mobile_creatable = True
mobile_rows_creatable = True
# set to False to disable "zero all" batch count mode
allow_zero_all = True
# set to False to disable "variance" batch count mode
allow_variance = True
# set to False to prevent exposing case fields for user input,
# when the batch count mode is "adjust only"
allow_adjustment_cases = True
@ -192,10 +186,10 @@ class InventoryBatchView(BatchMasterView):
modes.pop(self.enum.INVENTORY_MODE_REPLACE, None)
if hasattr(self.enum, 'INVENTORY_MODE_REPLACE_ADJUST'):
modes.pop(self.enum.INVENTORY_MODE_REPLACE_ADJUST, None)
if not self.allow_zero_all or not self.request.has_perm('{}.create.zero'.format(permission_prefix)):
if not self.handler.allow_zero_all or not self.request.has_perm('{}.create.zero'.format(permission_prefix)):
if hasattr(self.enum, 'INVENTORY_MODE_ZERO_ALL'):
modes.pop(self.enum.INVENTORY_MODE_ZERO_ALL, None)
if not self.allow_variance or not self.request.has_perm('{}.create.variance'.format(permission_prefix)):
if not self.handler.allow_variance or not self.request.has_perm('{}.create.variance'.format(permission_prefix)):
if hasattr(self.enum, 'INVENTORY_MODE_VARIANCE'):
modes.pop(self.enum.INVENTORY_MODE_VARIANCE, None)
return modes
@ -694,19 +688,24 @@ class InventoryBatchView(BatchMasterView):
@classmethod
def _inventory_defaults(cls, config):
rattail_config = config.registry.settings['rattail_config']
model_key = cls.get_model_key()
model_title = cls.get_model_title()
route_prefix = cls.get_route_prefix()
url_prefix = cls.get_url_prefix()
permission_prefix = cls.get_permission_prefix()
# we need batch handler to determine available permissions
factory = cls.get_handler_factory(rattail_config)
handler = factory(rattail_config)
# extra perms for creating batches per "mode"
config.add_tailbone_permission(permission_prefix, '{}.create.replace'.format(permission_prefix),
"Create new {} with 'replace' mode".format(model_title))
if cls.allow_zero_all:
if handler.allow_zero_all:
config.add_tailbone_permission(permission_prefix, '{}.create.zero'.format(permission_prefix),
"Create new {} with 'zero' mode".format(model_title))
if cls.allow_variance:
if handler.allow_variance:
config.add_tailbone_permission(permission_prefix, '{}.create.variance'.format(permission_prefix),
"Create new {} with 'variance' mode".format(model_title))