= Add Execution Options for a Batch = This assumes you already have a batch (table, handler, master view), and population / execution works as expected, but you wish to provide user with some options at the execution step. == Batch Handler == Ultimately the new execution options must be recognized and implemented by the batch handler, so that's our first step. Let's say we have a "pricing" batch handler and we want to let the user declare whether or not new labels should be deployed along with the new prices, and to which label printer if so. We might edit a class called `PricingBatchHandler` in a file like `~/src/poser/poser/batch/pricing.py`: {{{#!highlight python from rattail.batch import pricing as base class PricingBatchHandler(base.PricingBatchHandler): # must add new options to method signature def execute(self, batch, deploy_labels=False, label_printer=None, progress=None, **kwargs): # do whatever you normally do for execution here self.deploy_prices(batch, progress=progress) # check status of new option, and act accordingly if deploy_labels: self.deploy_labels(batch, label_printer, progress=progress) return True def deploy_labels(self, batch, label_printer, progress=None): # must do something here print("deploying labels to printer: %s" % label_printer) }}} == Batch Master View == Now that the batch handler will honor the new execution options, we declare them for the UI, in the batch master view. Note that the important part, is that you define this "execution options schema" such that its nodes correspond to the options accepted by your batch handler's `execute()` method, i.e. per the above step. They should match in both "name" and "data type". Here we might edit a class called `PricingBatchView` in a file like `~/src/poser/poser/web/views/batch/pricing.py`: {{{#!highlight python import colander from tailbone import forms from tailbone.views.batch import pricing as base POSSIBLE_PRINTERS = { 'zebra001': "Zebra #1", 'zebra002': "Zebra #2", 'cognitive001': "Cognitive #1", } # must add this; can call it whatever you like class ExecutionOptions(colander.Schema): # NOTE: these schema nodes must correspond in both name and type, # to the options accepted by handler's `execute()` method deploy_labels = colander.SchemaNode(colander.Bool()) label_printer = colander.SchemaNode( colander.String(), validator=colander.OneOf(POSSIBLE_PRINTERS), widget=forms.widgets.PlainSelectWidget(values=POSSIBLE_PRINTERS.items())) class PricingBatchView(base.PricingBatchView): # must add this; should refer to schema defined above execution_options_schema = ExecutionOptions }}}