diff --git a/tailbone/templates/products/batch.mako b/tailbone/templates/products/batch.mako
index bb6307dd..97b23035 100644
--- a/tailbone/templates/products/batch.mako
+++ b/tailbone/templates/products/batch.mako
@@ -1,4 +1,4 @@
-## -*- coding: utf-8 -*-
+## -*- coding: utf-8; -*-
<%inherit file="/base.mako" />
<%def name="title()">Products: Create Batch%def>
@@ -12,19 +12,12 @@
@@ -39,26 +32,41 @@
%def>
+<%def name="render_deform_field(field)">
+
- ${h.form(request.current_route_url())}
+ ${h.form(request.current_route_url(), class_='autodisable')}
${h.csrf_token(request)}
- ${self.wtfield(form, 'batch_type')}
+ ${render_deform_field(dform['batch_type'])}
+ ${render_deform_field(dform['description'])}
+ ${render_deform_field(dform['notes'])}
% for key, pform in params_forms.items():
- % for name in pform._fields:
- ${self.wtfield(pform, name)}
+ ## TODO: hacky to use deform? at least is explicit..
+ % for field in pform.make_deform_form():
+ ${render_deform_field(field)}
% endfor
% endfor
- Create Batch
+ ${h.submit('make-batch', "Create Batch")}
${h.link_to("Cancel", url('products'), class_='button')}
diff --git a/tailbone/views/products.py b/tailbone/views/products.py
index a8b9b33a..1eb2eb75 100644
--- a/tailbone/views/products.py
+++ b/tailbone/views/products.py
@@ -40,13 +40,14 @@ from rattail.exceptions import LabelPrintingError
from rattail.util import load_object, pretty_quantity
from rattail.batch import get_batch_handler
-import wtforms
+import colander
import formalchemy as fa
+from deform import widget as dfwidget
from pyramid import httpexceptions
from pyramid.renderers import render_to_response
from webhelpers2.html import tags, HTML
-from tailbone import forms, grids
+from tailbone import forms, forms2, grids
from tailbone.db import Session
from tailbone.views import MasterView2 as MasterView, AutocompleteView
from tailbone.progress import SessionProgress
@@ -483,60 +484,74 @@ class ProductsView(MasterView):
supported[key] = handler
batch_options.append((key, handler.get_model_title()))
- class MakeBatchForm(wtforms.Form):
- batch_type = wtforms.SelectField(choices=batch_options)
+ schema = colander.SchemaNode(
+ colander.Mapping(),
+ colander.SchemaNode(colander.String(), name='batch_type', widget=dfwidget.SelectWidget(values=batch_options)),
+ colander.SchemaNode(colander.String(), name='description', missing=colander.null),
+ colander.SchemaNode(colander.String(), name='notes', missing=colander.null),
+ )
+
+ form = forms2.Form(schema=schema, request=self.request,
+ cancel_url=self.get_index_url())
+ form.set_type('notes', 'text')
- form = MakeBatchForm(self.request.POST)
params_forms = {}
for key, handler in supported.items():
- make_form = getattr(self, 'make_batch_params_form_{}'.format(key), None)
- if make_form:
- params_forms[key] = make_form()
+ make_schema = getattr(self, 'make_batch_params_schema_{}'.format(key), None)
+ if make_schema:
+ schema = make_schema()
+ # must prefix node names with batch key, to guarantee unique
+ for node in schema:
+ node.param_name = node.name
+ node.name = '{}_{}'.format(key, node.name)
+ params_forms[key] = forms2.Form(schema=schema, request=self.request)
- if self.request.method == 'POST' and form.validate():
- batch_key = form.batch_type.data
- params = {}
+ if self.request.method == 'POST':
+ controls = self.request.POST.items()
+ data = form.validate(controls)
+ batch_key = data['batch_type']
+ params = {
+ 'description': data['description'],
+ 'notes': data['notes']}
pform = params_forms.get(batch_key)
- if not pform or pform.validate(): # params form must validate if present
- if pform:
- params = dict((name, pform[name].data) for name in pform._fields)
- handler = get_batch_handler(self.rattail_config, batch_key,
- default=supported[batch_key].spec)
- products = self.get_effective_data()
- progress = SessionProgress(self.request, 'products.batch')
- thread = Thread(target=self.make_batch_thread,
- args=(handler, self.request.user.uuid, products, params, progress))
- thread.start()
- return self.render_progress(progress, {
- 'cancel_url': self.get_index_url(),
- 'cancel_msg': "Batch creation was canceled.",
- })
-
- return {'form': form, 'params_forms': params_forms}
+ if pform:
+ pdata = pform.validate(controls)
+ for field in pform:
+ param_name = pform.schema[field.name].param_name
+ params[param_name] = pdata[field.name]
- def make_batch_params_form_labels(self):
- """
- Returns a wtforms.Form object with param fields for making a new
- Labels Batch.
- """
- class LabelsParamsForm(wtforms.Form):
- description = wtforms.StringField()
- notes = wtforms.TextAreaField()
+ # TODO: should this be done elsewhere?
+ for name in params:
+ if params[name] is colander.null:
+ params[name] = None
- return LabelsParamsForm(self.request.POST)
+ handler = get_batch_handler(self.rattail_config, batch_key,
+ default=supported[batch_key].spec)
+ products = self.get_effective_data()
+ progress = SessionProgress(self.request, 'products.batch')
+ thread = Thread(target=self.make_batch_thread,
+ args=(handler, self.request.user.uuid, products, params, progress))
+ thread.start()
+ return self.render_progress(progress, {
+ 'cancel_url': self.get_index_url(),
+ 'cancel_msg': "Batch creation was canceled.",
+ })
- def make_batch_params_form_pricing(self):
- """
- Returns a wtforms.Form object with param fields for making a new
- Pricing Batch.
- """
- class PricingParamsForm(wtforms.Form):
- description = wtforms.StringField()
- min_diff_threshold = wtforms.DecimalField(places=2, validators=[wtforms.validators.optional()])
- calculate_for_manual = wtforms.BooleanField()
- notes = wtforms.TextAreaField()
+ return {
+ 'form': form,
+ 'dform': form.make_deform_form(), # TODO: hacky? at least is explicit..
+ 'params_forms': params_forms,
+ }
- return PricingParamsForm(self.request.POST)
+ def make_batch_params_schema_pricing(self):
+ """
+ Return params schema for making a pricing batch.
+ """
+ return colander.SchemaNode(
+ colander.Mapping(),
+ colander.SchemaNode(colander.Decimal(), name='min_diff_threshold', quant='1.00', missing=colander.null),
+ colander.SchemaNode(colander.Boolean(), name='calculate_for_manual'),
+ )
def make_batch_thread(self, handler, user_uuid, products, params, progress):
"""