Add min diff threshold param when making price batch from product query

Hopefully this sets the stage for arbitrary batch params here..
This commit is contained in:
Lance Edgar 2017-01-30 16:11:29 -06:00
parent 2ab2dfe26b
commit e452ea1ae9
5 changed files with 107 additions and 57 deletions

View file

@ -90,6 +90,7 @@ requires = [
'transaction', # 1.2.0 'transaction', # 1.2.0
'waitress', # 0.8.1 'waitress', # 0.8.1
'WebHelpers', # 1.3 'WebHelpers', # 1.3
'WTForms', # 2.1
'zope.sqlalchemy', # 0.7 'zope.sqlalchemy', # 0.7
# TODO: Need to figure out what to do about this... # TODO: Need to figure out what to do about this...

View file

@ -7,12 +7,20 @@
<li>${h.link_to("Back to Products", url('products'))}</li> <li>${h.link_to("Back to Products", url('products'))}</li>
</%def> </%def>
<%def name="head_tags()"> <%def name="extra_javascript()">
${parent.head_tags()} ${parent.extra_javascript()}
% if legacy_mode is Undefined:
<script type="text/javascript"> <script type="text/javascript">
$(function() { $(function() {
$('#batch_type').selectmenu(); $('#batch_type').selectmenu({
change: function(event, ui) {
$('.params-wrapper').hide();
$('.params-wrapper.' + ui.item.value).show();
}
});
$('.params-wrapper.' + $('#batch_type').val()).show();
$('#make-batch').click(function() { $('#make-batch').click(function() {
$(this).button('disable').button('option', 'label', "Working, please wait..."); $(this).button('disable').button('option', 'label', "Working, please wait...");
@ -21,41 +29,29 @@
}); });
</script> </script>
% endif
</%def>
<%def name="extra_styles()">
${parent.extra_styles()}
% if legacy_mode is Undefined:
<style type="text/css">
.params-wrapper {
display: none;
}
</style>
% endif
</%def> </%def>
<ul id="context-menu"> <ul id="context-menu">
${self.context_menu_items()} ${self.context_menu_items()}
</ul> </ul>
% if supported_batches is not Undefined: <div class="form">
<div class="form">
${h.form(request.current_route_url())} ${h.form(request.current_route_url())}
${h.csrf_token(request)} ${h.csrf_token(request)}
<div class="field-wrapper"> % if legacy_mode is not Undefined:
<label for="batch_type">Batch Type</label>
<div class="field">
${h.select('batch_type', None, supported_batches)}
</div>
</div>
<div class="buttons">
<button type="button" id="make-batch">Create Batch</button>
${h.link_to("Cancel", url('products'), class_='button')}
</div>
${h.end_form()}
</div>
% else: ## legacy mode
<div class="form">
${h.form(request.current_route_url())}
${h.csrf_token(request)}
<div class="field-wrapper"> <div class="field-wrapper">
<label for="provider">Batch Type</label> <label for="provider">Batch Type</label>
@ -69,8 +65,24 @@
${h.link_to("Cancel", url('products'), class_='button')} ${h.link_to("Cancel", url('products'), class_='button')}
</div> </div>
${h.end_form()} % else: ## new-style batches
${self.wtfield(form, 'batch_type')}
% for key, pform in params_forms.items():
<div class="params-wrapper ${key}">
% for name in pform._fields:
${self.wtfield(pform, name)}
% endfor
</div>
% endfor
<div class="buttons">
<button type="button" id="make-batch">Create Batch</button>
${h.link_to("Cancel", url('products'), class_='button')}
</div> </div>
% endif % endif
${h.end_form()}
</div>

View file

@ -130,3 +130,12 @@
<%def name="footer()"> <%def name="footer()">
powered by ${h.link_to("Rattail", url('about'))} powered by ${h.link_to("Rattail", url('about'))}
</%def> </%def>
<%def name="wtfield(form, name, **kwargs)">
<div class="field-wrapper${' error' if form[name].errors else ''}">
<label for="${name}">${form[name].label}</label>
<div class="field">
${form[name](**kwargs)}
</div>
</div>
</%def>

View file

@ -43,13 +43,13 @@ class PricingBatchView(BatchMasterView):
route_prefix = 'batch.pricing' route_prefix = 'batch.pricing'
url_prefix = '/batches/pricing' url_prefix = '/batches/pricing'
creatable = False creatable = False
editable = False
rows_editable = True rows_editable = True
def configure_fieldset(self, fs): def configure_fieldset(self, fs):
fs.configure( fs.configure(
include=[ include=[
fs.id, fs.id,
fs.min_diff_threshold,
fs.created, fs.created,
fs.created_by, fs.created_by,
fs.executed, fs.executed,

View file

@ -40,6 +40,7 @@ from rattail.exceptions import LabelPrintingError
from rattail.util import load_object from rattail.util import load_object
from rattail.batch import get_batch_handler from rattail.batch import get_batch_handler
import wtforms
import formalchemy as fa import formalchemy as fa
from pyramid import httpexceptions from pyramid import httpexceptions
from pyramid.renderers import render_to_response from pyramid.renderers import render_to_response
@ -399,38 +400,65 @@ class ProductsView(MasterView):
# okay then, new-style it is # okay then, new-style it is
supported = self.get_supported_batches() supported = self.get_supported_batches()
batch_options = []
for key, spec in list(supported.items()):
handler = load_object(spec)(self.rattail_config)
handler.spec = spec
supported[key] = handler
batch_options.append((key, handler.get_model_title()))
if self.request.method == 'POST': class MakeBatchForm(wtforms.Form):
batch_key = self.request.POST.get('batch_type') batch_type = wtforms.SelectField(choices=batch_options)
if batch_key and batch_key in supported:
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()
if self.request.method == 'POST' and form.validate():
batch_key = form.batch_type.data
params = {}
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, handler = get_batch_handler(self.rattail_config, batch_key,
default=supported[batch_key]) default=supported[batch_key].spec)
products = self.get_effective_data() products = self.get_effective_data()
progress = SessionProgress(self.request, 'products.batch') progress_key = 'products.batch'
progress = SessionProgress(self.request, progress_key)
thread = Thread(target=self.make_batch_thread, thread = Thread(target=self.make_batch_thread,
args=(handler, self.request.user.uuid, products, progress)) args=(handler, self.request.user.uuid, products, params, progress))
thread.start() thread.start()
return self.render_progress({ return self.render_progress({
'key': 'products.batch', 'key': progress_key,
'cancel_url': self.get_index_url(), 'cancel_url': self.get_index_url(),
'cancel_msg': "Batch creation was canceled.", 'cancel_msg': "Batch creation was canceled.",
}) })
batch_types = [] return {'form': form, 'params_forms': params_forms}
for key, spec in supported.iteritems():
handler = load_object(spec)(self.rattail_config)
batch_types.append((key, handler.get_model_title()))
return {'supported_batches': batch_types} 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):
min_diff_threshold = wtforms.DecimalField(places=2, validators=[wtforms.validators.optional()])
def make_batch_thread(self, handler, user_uuid, products, progress): return PricingParamsForm(self.request.POST)
def make_batch_thread(self, handler, user_uuid, products, params, progress):
""" """
Threat target for making a batch from current products query. Threat target for making a batch from current products query.
""" """
session = RattailSession() session = RattailSession()
user = session.query(model.User).get(user_uuid) user = session.query(model.User).get(user_uuid)
assert user assert user
batch = handler.make_batch(session, created_by=user) params['created_by'] = user
batch = handler.make_batch(session, **params)
batch.products = products.with_session(session).all() batch.products = products.with_session(session).all()
handler.make_initial_rows(batch, progress=progress) handler.make_initial_rows(batch, progress=progress)
@ -483,7 +511,7 @@ class ProductsView(MasterView):
providers = [(p.name, p.description) providers = [(p.name, p.description)
for p in sorted(providers.itervalues(), for p in sorted(providers.itervalues(),
key=lambda p: p.description)] key=lambda p: p.description)]
return {'providers': providers} return {'legacy_mode': True, 'providers': providers}
def make_batch_thread_legacy(self, provider, progress): def make_batch_thread_legacy(self, provider, progress):
""" """