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 @@ -12,19 +12,12 @@ @@ -39,26 +32,41 @@ +<%def name="render_deform_field(field)"> +
+
+ +
+ ${field.serialize()|n} +
+
+
+ + +
- ${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
- + ${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): """