From 0704717ec5d97fcbe5691aa3d5c6e356dd782990 Mon Sep 17 00:00:00 2001 From: Lance Edgar Date: Sun, 29 Mar 2020 12:46:41 -0500 Subject: [PATCH] Let inventory batch handler declare which count modes are allowed preparing for API/mobile usage --- tailbone/views/batch/core.py | 41 +++++++++++++++++++++---------- tailbone/views/batch/inventory.py | 19 +++++++------- 2 files changed, 37 insertions(+), 23 deletions(-) diff --git a/tailbone/views/batch/core.py b/tailbone/views/batch/core.py index dbde90cb..e3e14ee8 100644 --- a/tailbone/views/batch/core.py +++ b/tailbone/views/batch/core.py @@ -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) diff --git a/tailbone/views/batch/inventory.py b/tailbone/views/batch/inventory.py index f6ac4221..d7780467 100644 --- a/tailbone/views/batch/inventory.py +++ b/tailbone/views/batch/inventory.py @@ -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))