Add initial support for receiving truck dump batch via mobile
i.e. just the initial truck dump, but secondary invoice batches are not yet supported. also this maybe breaks other things..we'll see
This commit is contained in:
parent
b515331e48
commit
9ed501a8cc
|
@ -153,6 +153,13 @@ class EmployeeType(ModelType):
|
||||||
model_class = model.Employee
|
model_class = model.Employee
|
||||||
|
|
||||||
|
|
||||||
|
class VendorType(ModelType):
|
||||||
|
"""
|
||||||
|
Custom schema type for vendor relationship field.
|
||||||
|
"""
|
||||||
|
model_class = model.Vendor
|
||||||
|
|
||||||
|
|
||||||
class ProductType(ModelType):
|
class ProductType(ModelType):
|
||||||
"""
|
"""
|
||||||
Custom schema type for product relationship field.
|
Custom schema type for product relationship field.
|
||||||
|
|
|
@ -56,10 +56,12 @@
|
||||||
// when user clicks autocomplete result, hide search etc.
|
// when user clicks autocomplete result, hide search etc.
|
||||||
this.ul.on('click', 'li', function() {
|
this.ul.on('click', 'li', function() {
|
||||||
var $li = $(this);
|
var $li = $(this);
|
||||||
|
var uuid = $li.data('uuid');
|
||||||
that.search.hide();
|
that.search.hide();
|
||||||
that.hidden_field.val($li.data('uuid'));
|
that.hidden_field.val(uuid);
|
||||||
that.button.text($li.text()).show();
|
that.button.text($li.text()).show();
|
||||||
that.ul.hide();
|
that.ul.hide();
|
||||||
|
that.element.trigger('autocompleteitemselected', uuid);
|
||||||
});
|
});
|
||||||
|
|
||||||
// when user clicks "change" button, show search etc.
|
// when user clicks "change" button, show search etc.
|
||||||
|
@ -69,6 +71,7 @@
|
||||||
that.hidden_field.val('');
|
that.hidden_field.val('');
|
||||||
that.search.show();
|
that.search.show();
|
||||||
that.text_field.focus();
|
that.text_field.focus();
|
||||||
|
that.element.trigger('autocompleteitemcleared');
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
34
tailbone/static/js/tailbone.mobile.receiving.js
Normal file
34
tailbone/static/js/tailbone.mobile.receiving.js
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
|
||||||
|
/************************************************************
|
||||||
|
*
|
||||||
|
* tailbone.mobile.receiving.js
|
||||||
|
*
|
||||||
|
* Global logic for mobile receiving feature
|
||||||
|
*
|
||||||
|
************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: this is really just for receiving; should change form name?
|
||||||
|
$(document).on('autocompleteitemselected', 'form[name="new-purchasing-batch"] .vendor', function(event, uuid) {
|
||||||
|
$('#new-receiving-types').show();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: this is really just for receiving; should change form name?
|
||||||
|
$(document).on('autocompleteitemcleared', 'form[name="new-purchasing-batch"] .vendor', function(event) {
|
||||||
|
$('#new-receiving-types').hide();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$(document).on('click', 'form[name="new-purchasing-batch"] #receive-truck-dump', function() {
|
||||||
|
var form = $(this).parents('form');
|
||||||
|
form.find('input[name="workflow"]').val('truck_dump');
|
||||||
|
form.submit();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$(document).on('click', 'form.receiving-update #delete-receiving-row', function() {
|
||||||
|
var form = $(this).parents('form');
|
||||||
|
form.find('input[name="delete_row"]').val('true');
|
||||||
|
form.submit();
|
||||||
|
});
|
|
@ -75,7 +75,7 @@
|
||||||
|
|
||||||
${rows_grid|n}
|
${rows_grid|n}
|
||||||
|
|
||||||
% if not batch.executed:
|
% if master.handler.executable(batch) and not batch.executed:
|
||||||
<div id="execution-options-dialog" style="display: none;">
|
<div id="execution-options-dialog" style="display: none;">
|
||||||
${execute_form.render_deform(form_kwargs={'name': 'batch-execution'}, buttons=False)|n}
|
${execute_form.render_deform(form_kwargs={'name': 'batch-execution'}, buttons=False)|n}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
${h.javascript_link('https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js')}
|
${h.javascript_link('https://code.jquery.com/mobile/1.4.5/jquery.mobile-1.4.5.min.js')}
|
||||||
${h.javascript_link(request.static_url('tailbone:static/js/jquery.ui.tailbone.mobile.js'))}
|
${h.javascript_link(request.static_url('tailbone:static/js/jquery.ui.tailbone.mobile.js'))}
|
||||||
${h.javascript_link(request.static_url('tailbone:static/js/tailbone.mobile.js'))}
|
${h.javascript_link(request.static_url('tailbone:static/js/tailbone.mobile.js'))}
|
||||||
|
${h.javascript_link(request.static_url('tailbone:static/js/tailbone.mobile.receiving.js'))}
|
||||||
${self.extra_javascript()}
|
${self.extra_javascript()}
|
||||||
|
|
||||||
## since jquery mobile will "utterly cache" the first page which is loaded
|
## since jquery mobile will "utterly cache" the first page which is loaded
|
||||||
|
|
|
@ -20,8 +20,25 @@ ${h.csrf_token(request)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
${h.submit('submit', "Find purchase orders")}
|
|
||||||
## <button type="button">New receiving from scratch</button>
|
<div id="new-receiving-types" style="display: none;">
|
||||||
|
|
||||||
|
${h.hidden('workflow')}
|
||||||
|
|
||||||
|
% if master.allow_from_po:
|
||||||
|
## ${h.submit('submit', "Find purchase orders")}
|
||||||
|
<button type="button">Receive from PO</button>
|
||||||
|
% endif
|
||||||
|
|
||||||
|
% if master.allow_from_scratch:
|
||||||
|
<button type="button">Receive from Scratch</button>
|
||||||
|
% endif
|
||||||
|
|
||||||
|
% if master.allow_truck_dump:
|
||||||
|
<button type="button" id="receive-truck-dump">Receive Truck Dump</button>
|
||||||
|
% endif
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
% else: ## vendor is known
|
% else: ## vendor is known
|
||||||
|
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
<%inherit file="/mobile/master/view_row.mako" />
|
<%inherit file="/mobile/master/view_row.mako" />
|
||||||
<%namespace file="/mobile/keypad.mako" import="keypad" />
|
<%namespace file="/mobile/keypad.mako" import="keypad" />
|
||||||
|
|
||||||
<%def name="title()">Receiving » ${instance.batch.id_str} » ${row.upc.pretty()}</%def>
|
<%def name="title()">Receiving » ${batch.id_str} » ${row.upc.pretty()}</%def>
|
||||||
|
|
||||||
<%def name="page_title()">${h.link_to("Receiving", url('mobile.receiving'))} » ${h.link_to(instance.batch.id_str, url('mobile.receiving.view', uuid=instance.batch_uuid))} » ${row.upc.pretty()}</%def>
|
<%def name="page_title()">${h.link_to("Receiving", url('mobile.receiving'))} » ${h.link_to(batch.id_str, url('mobile.receiving.view', uuid=batch.uuid))} » ${row.upc.pretty()}</%def>
|
||||||
|
|
||||||
<%
|
<%
|
||||||
unit_uom = 'LB' if row.product and row.product.weighed else 'EA'
|
unit_uom = 'LB' if row.product and row.product.weighed else 'EA'
|
||||||
|
@ -20,7 +20,7 @@
|
||||||
% if instance.product:
|
% if instance.product:
|
||||||
<h3>${instance.brand_name or ""}</h3>
|
<h3>${instance.brand_name or ""}</h3>
|
||||||
<h3>${instance.description} ${instance.size}</h3>
|
<h3>${instance.description} ${instance.size}</h3>
|
||||||
<h3>${h.pretty_quantity(row.case_quantity)} ${unit_uom} per CS</h3>
|
<h3>1 CS = ${h.pretty_quantity(row.case_quantity)} ${unit_uom}</h3>
|
||||||
% else:
|
% else:
|
||||||
<h3>${instance.description}</h3>
|
<h3>${instance.description}</h3>
|
||||||
% endif
|
% endif
|
||||||
|
@ -32,10 +32,12 @@
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<tbody>
|
<tbody>
|
||||||
|
% if not batch.truck_dump:
|
||||||
<tr>
|
<tr>
|
||||||
<td>ordered</td>
|
<td>ordered</td>
|
||||||
<td>${h.pretty_quantity(row.cases_ordered or 0)} / ${h.pretty_quantity(row.units_ordered or 0)}</td>
|
<td>${h.pretty_quantity(row.cases_ordered or 0)} / ${h.pretty_quantity(row.units_ordered or 0)}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
% endif
|
||||||
<tr>
|
<tr>
|
||||||
<td>received</td>
|
<td>received</td>
|
||||||
<td>${h.pretty_quantity(row.cases_received or 0)} / ${h.pretty_quantity(row.units_received or 0)}</td>
|
<td>${h.pretty_quantity(row.cases_received or 0)} / ${h.pretty_quantity(row.units_received or 0)}</td>
|
||||||
|
@ -57,7 +59,7 @@
|
||||||
% endfor
|
% endfor
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
% if not instance.batch.executed and not instance.batch.complete:
|
% if not batch.executed and not batch.complete:
|
||||||
|
|
||||||
${h.form(request.current_route_url(), class_='receiving-update')}
|
${h.form(request.current_route_url(), class_='receiving-update')}
|
||||||
${h.csrf_token(request)}
|
${h.csrf_token(request)}
|
||||||
|
@ -98,5 +100,10 @@
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
${h.hidden('delete_row', value='false')}
|
||||||
|
% if request.has_perm('{}.delete_row'.format(permission_prefix)):
|
||||||
|
<button type="button" id="delete-receiving-row">Delete this Row</button>
|
||||||
|
% endif
|
||||||
|
|
||||||
${h.end_form()}
|
${h.end_form()}
|
||||||
% endif
|
% endif
|
||||||
|
|
|
@ -512,6 +512,7 @@ class PurchasingBatchView(BatchMasterView):
|
||||||
def get_batch_kwargs(self, batch, mobile=False):
|
def get_batch_kwargs(self, batch, mobile=False):
|
||||||
kwargs = super(PurchasingBatchView, self).get_batch_kwargs(batch, mobile=mobile)
|
kwargs = super(PurchasingBatchView, self).get_batch_kwargs(batch, mobile=mobile)
|
||||||
kwargs['mode'] = self.batch_mode
|
kwargs['mode'] = self.batch_mode
|
||||||
|
kwargs['truck_dump'] = batch.truck_dump
|
||||||
if batch.store:
|
if batch.store:
|
||||||
kwargs['store'] = batch.store
|
kwargs['store'] = batch.store
|
||||||
elif batch.store_uuid:
|
elif batch.store_uuid:
|
||||||
|
|
|
@ -36,6 +36,8 @@ from rattail.gpc import GPC
|
||||||
from rattail.util import pretty_quantity, prettify
|
from rattail.util import pretty_quantity, prettify
|
||||||
|
|
||||||
import colander
|
import colander
|
||||||
|
from deform import widget as dfwidget
|
||||||
|
from pyramid import httpexceptions
|
||||||
from webhelpers2.html import tags
|
from webhelpers2.html import tags
|
||||||
|
|
||||||
from tailbone import forms, grids
|
from tailbone import forms, grids
|
||||||
|
@ -48,6 +50,12 @@ class MobileItemStatusFilter(grids.filters.MobileFilter):
|
||||||
|
|
||||||
def filter_equal(self, query, value):
|
def filter_equal(self, query, value):
|
||||||
|
|
||||||
|
# NOTE: this is only relevant for truck dump
|
||||||
|
if value == 'received':
|
||||||
|
return query.filter(sa.or_(
|
||||||
|
model.PurchaseBatchRow.cases_received != 0,
|
||||||
|
model.PurchaseBatchRow.units_received != 0))
|
||||||
|
|
||||||
# TODO: is this accurate (enough) ?
|
# TODO: is this accurate (enough) ?
|
||||||
if value == 'incomplete':
|
if value == 'incomplete':
|
||||||
return query.filter(sa.or_(model.PurchaseBatchRow.cases_ordered != 0, model.PurchaseBatchRow.units_ordered != 0))\
|
return query.filter(sa.or_(model.PurchaseBatchRow.cases_ordered != 0, model.PurchaseBatchRow.units_ordered != 0))\
|
||||||
|
@ -95,10 +103,29 @@ class ReceivingBatchView(PurchasingBatchView):
|
||||||
mobile_rows_filterable = True
|
mobile_rows_filterable = True
|
||||||
mobile_rows_creatable = True
|
mobile_rows_creatable = True
|
||||||
|
|
||||||
|
allow_from_po = False
|
||||||
|
allow_from_scratch = True
|
||||||
|
allow_truck_dump = False
|
||||||
|
|
||||||
|
grid_columns = [
|
||||||
|
'id',
|
||||||
|
'vendor',
|
||||||
|
'truck_dump',
|
||||||
|
'department',
|
||||||
|
'buyer',
|
||||||
|
'date_ordered',
|
||||||
|
'created',
|
||||||
|
'created_by',
|
||||||
|
'rowcount',
|
||||||
|
'status_code',
|
||||||
|
'executed',
|
||||||
|
]
|
||||||
|
|
||||||
form_fields = [
|
form_fields = [
|
||||||
'id',
|
'id',
|
||||||
'store',
|
'store',
|
||||||
'vendor',
|
'vendor',
|
||||||
|
'truck_dump',
|
||||||
'department',
|
'department',
|
||||||
'purchase',
|
'purchase',
|
||||||
'vendor_email',
|
'vendor_email',
|
||||||
|
@ -123,6 +150,7 @@ class ReceivingBatchView(PurchasingBatchView):
|
||||||
|
|
||||||
mobile_form_fields = [
|
mobile_form_fields = [
|
||||||
'vendor',
|
'vendor',
|
||||||
|
'truck_dump',
|
||||||
'department',
|
'department',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -175,6 +203,13 @@ class ReceivingBatchView(PurchasingBatchView):
|
||||||
def batch_mode(self):
|
def batch_mode(self):
|
||||||
return self.enum.PURCHASE_BATCH_MODE_RECEIVING
|
return self.enum.PURCHASE_BATCH_MODE_RECEIVING
|
||||||
|
|
||||||
|
def configure_form(self, f):
|
||||||
|
super(ReceivingBatchView, self).configure_form(f)
|
||||||
|
|
||||||
|
# truck_dump
|
||||||
|
if self.editing:
|
||||||
|
f.set_readonly('truck_dump')
|
||||||
|
|
||||||
def render_mobile_listitem(self, batch, i):
|
def render_mobile_listitem(self, batch, i):
|
||||||
title = "({}) {} for ${:0,.2f} - {}, {}".format(
|
title = "({}) {} for ${:0,.2f} - {}, {}".format(
|
||||||
batch.id_str,
|
batch.id_str,
|
||||||
|
@ -188,8 +223,17 @@ class ReceivingBatchView(PurchasingBatchView):
|
||||||
"""
|
"""
|
||||||
Returns a set of filters for the mobile row grid.
|
Returns a set of filters for the mobile row grid.
|
||||||
"""
|
"""
|
||||||
|
batch = self.get_instance()
|
||||||
filters = grids.filters.GridFilterSet()
|
filters = grids.filters.GridFilterSet()
|
||||||
filters['status'] = MobileItemStatusFilter('status', default_value='incomplete')
|
if batch.truck_dump:
|
||||||
|
value_choices = ['received', 'damaged', 'expired', 'all']
|
||||||
|
default_status = 'all'
|
||||||
|
else:
|
||||||
|
value_choices = ['incomplete', 'unexpected', 'damaged', 'expired', 'all']
|
||||||
|
default_status = 'incomplete'
|
||||||
|
filters['status'] = MobileItemStatusFilter('status',
|
||||||
|
value_choices=value_choices,
|
||||||
|
default_value=default_status)
|
||||||
return filters
|
return filters
|
||||||
|
|
||||||
def mobile_create(self):
|
def mobile_create(self):
|
||||||
|
@ -199,6 +243,25 @@ class ReceivingBatchView(PurchasingBatchView):
|
||||||
mode = self.batch_mode
|
mode = self.batch_mode
|
||||||
data = {'mode': mode}
|
data = {'mode': mode}
|
||||||
|
|
||||||
|
form = forms.Form(schema=MobileNewReceivingBatch(), request=self.request)
|
||||||
|
if form.validate(newstyle=True):
|
||||||
|
|
||||||
|
if form.validated['workflow'] == 'truck_dump':
|
||||||
|
if not self.allow_truck_dump:
|
||||||
|
raise NotImplementedError("Requested workflow not supported: truck_dump")
|
||||||
|
batch = self.model_class()
|
||||||
|
batch.store = self.rattail_config.get_store(self.Session())
|
||||||
|
batch.mode = mode
|
||||||
|
batch.truck_dump = True
|
||||||
|
batch.vendor = self.Session.merge(form.validated['vendor'])
|
||||||
|
batch.created_by = self.request.user
|
||||||
|
kwargs = self.get_batch_kwargs(batch, mobile=True)
|
||||||
|
batch = self.handler.make_batch(self.Session(), **kwargs)
|
||||||
|
return self.redirect(self.request.route_url('mobile.receiving.view', uuid=batch.uuid))
|
||||||
|
|
||||||
|
else:
|
||||||
|
raise NotImplementedError("Requested workflow not supported: {}".format(form.validated['workflow']))
|
||||||
|
|
||||||
vendor = None
|
vendor = None
|
||||||
if self.request.method == 'POST' and self.request.POST.get('vendor'):
|
if self.request.method == 'POST' and self.request.POST.get('vendor'):
|
||||||
vendor = self.Session.query(model.Vendor).get(self.request.POST['vendor'])
|
vendor = self.Session.query(model.Vendor).get(self.request.POST['vendor'])
|
||||||
|
@ -227,28 +290,19 @@ class ReceivingBatchView(PurchasingBatchView):
|
||||||
data['purchases'] = [(p['key'], p['display']) for p in purchases['purchases']]
|
data['purchases'] = [(p['key'], p['display']) for p in purchases['purchases']]
|
||||||
return self.render_to_response('create', data, mobile=True)
|
return self.render_to_response('create', data, mobile=True)
|
||||||
|
|
||||||
def get_batch_kwargs(self, batch, mobile=False):
|
|
||||||
kwargs = super(ReceivingBatchView, self).get_batch_kwargs(batch, mobile=mobile)
|
|
||||||
if mobile:
|
|
||||||
|
|
||||||
purchase = self.get_purchase(self.request.POST['purchase'])
|
|
||||||
numbers = [d.F03 for d in purchase.details]
|
|
||||||
if numbers:
|
|
||||||
number = max(set(numbers), key=numbers.count)
|
|
||||||
kwargs['department'] = self.Session.query(model.Department)\
|
|
||||||
.filter(model.Department.number == number)\
|
|
||||||
.one()
|
|
||||||
|
|
||||||
return kwargs
|
|
||||||
|
|
||||||
def configure_mobile_form(self, f):
|
def configure_mobile_form(self, f):
|
||||||
super(ReceivingBatchView, self).configure_mobile_form(f)
|
super(ReceivingBatchView, self).configure_mobile_form(f)
|
||||||
|
batch = f.model_instance
|
||||||
|
|
||||||
# vendor
|
# truck_dump
|
||||||
# fs.vendor.with_renderer(fa.TextFieldRenderer),
|
if not self.creating:
|
||||||
|
if not batch.truck_dump:
|
||||||
|
f.remove_field('truck_dump')
|
||||||
|
|
||||||
# department
|
# department
|
||||||
# fs.department.with_renderer(fa.TextFieldRenderer),
|
if not self.creating:
|
||||||
|
if batch.truck_dump:
|
||||||
|
f.remove_field('department')
|
||||||
|
|
||||||
def configure_row_form(self, f):
|
def configure_row_form(self, f):
|
||||||
super(ReceivingBatchView, self).configure_row_form(f)
|
super(ReceivingBatchView, self).configure_row_form(f)
|
||||||
|
@ -302,8 +356,7 @@ class ReceivingBatchView(PurchasingBatchView):
|
||||||
if product:
|
if product:
|
||||||
row = model.PurchaseBatchRow()
|
row = model.PurchaseBatchRow()
|
||||||
row.product = product
|
row.product = product
|
||||||
batch.add_row(row)
|
self.handler.add_row(batch, row)
|
||||||
self.handler.refresh_row(row)
|
|
||||||
|
|
||||||
# check for "bad" upc
|
# check for "bad" upc
|
||||||
elif len(upc) > 14:
|
elif len(upc) > 14:
|
||||||
|
@ -329,9 +382,12 @@ class ReceivingBatchView(PurchasingBatchView):
|
||||||
"""
|
"""
|
||||||
self.viewing = True
|
self.viewing = True
|
||||||
row = self.get_row_instance()
|
row = self.get_row_instance()
|
||||||
|
batch = row.batch
|
||||||
|
permission_prefix = self.get_permission_prefix()
|
||||||
form = self.make_mobile_row_form(row)
|
form = self.make_mobile_row_form(row)
|
||||||
context = {
|
context = {
|
||||||
'row': row,
|
'row': row,
|
||||||
|
'batch': batch,
|
||||||
'instance': row,
|
'instance': row,
|
||||||
'instance_title': self.get_row_instance_title(row),
|
'instance_title': self.get_row_instance_title(row),
|
||||||
'parent_model_title': self.get_model_title(),
|
'parent_model_title': self.get_model_title(),
|
||||||
|
@ -339,10 +395,19 @@ class ReceivingBatchView(PurchasingBatchView):
|
||||||
'form': form,
|
'form': form,
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.request.has_perm('{}.create_row'.format(self.get_permission_prefix())):
|
if self.request.has_perm('{}.create_row'.format(permission_prefix)):
|
||||||
update_form = forms.Form(schema=ReceivingForm(), request=self.request)
|
update_form = forms.Form(schema=MobileReceivingForm(), request=self.request)
|
||||||
if update_form.validate(newstyle=True):
|
if update_form.validate(newstyle=True):
|
||||||
row = self.Session.merge(update_form.validated['row'])
|
row = self.Session.merge(update_form.validated['row'])
|
||||||
|
|
||||||
|
# TODO: surely this (delete_row) should be split out to a separate view
|
||||||
|
if update_form.validated['delete_row']:
|
||||||
|
if not self.request.has_perm('{}.delete_row'.format(permission_prefix)):
|
||||||
|
raise httpexceptions.HTTPForbidden()
|
||||||
|
self.handler.remove_row(row)
|
||||||
|
return self.redirect(self.get_action_url('view', batch, mobile=True))
|
||||||
|
|
||||||
|
else: # not delete_row
|
||||||
mode = update_form.validated['mode']
|
mode = update_form.validated['mode']
|
||||||
cases = update_form.validated['cases']
|
cases = update_form.validated['cases']
|
||||||
units = update_form.validated['units']
|
units = update_form.validated['units']
|
||||||
|
@ -363,12 +428,12 @@ class ReceivingBatchView(PurchasingBatchView):
|
||||||
|
|
||||||
# first undo any totals previously in effect for the row, then refresh
|
# first undo any totals previously in effect for the row, then refresh
|
||||||
if row.invoice_total:
|
if row.invoice_total:
|
||||||
row.batch.invoice_total -= row.invoice_total
|
batch.invoice_total -= row.invoice_total
|
||||||
self.handler.refresh_row(row)
|
self.handler.refresh_row(row)
|
||||||
|
|
||||||
return self.redirect(self.request.route_url('mobile.{}.view'.format(self.get_route_prefix()), uuid=row.batch_uuid))
|
return self.redirect(self.get_action_url('view', batch, mobile=True))
|
||||||
|
|
||||||
if not row.cases_ordered and not row.units_ordered:
|
if not row.cases_ordered and not row.units_ordered and not batch.truck_dump:
|
||||||
self.request.session.flash("This item was NOT on the original purchase order.", 'receiving-warning')
|
self.request.session.flash("This item was NOT on the original purchase order.", 'receiving-warning')
|
||||||
return self.render_to_response('view_row', context, mobile=True)
|
return self.render_to_response('view_row', context, mobile=True)
|
||||||
|
|
||||||
|
@ -438,12 +503,25 @@ class PurchaseBatchRowType(forms.types.ObjectType):
|
||||||
return row
|
return row
|
||||||
|
|
||||||
|
|
||||||
class ReceivingForm(colander.MappingSchema):
|
class MobileNewReceivingBatch(colander.MappingSchema):
|
||||||
|
|
||||||
|
vendor = colander.SchemaNode(forms.types.VendorType())
|
||||||
|
|
||||||
|
workflow = colander.SchemaNode(colander.String(),
|
||||||
|
validator=colander.OneOf([
|
||||||
|
'from_po',
|
||||||
|
'from_scratch',
|
||||||
|
'truck_dump',
|
||||||
|
]))
|
||||||
|
|
||||||
|
|
||||||
|
class MobileReceivingForm(colander.MappingSchema):
|
||||||
|
|
||||||
row = colander.SchemaNode(PurchaseBatchRowType())
|
row = colander.SchemaNode(PurchaseBatchRowType())
|
||||||
|
|
||||||
mode = colander.SchemaNode(colander.String(),
|
mode = colander.SchemaNode(colander.String(),
|
||||||
validator=colander.OneOf(['received',
|
validator=colander.OneOf([
|
||||||
|
'received',
|
||||||
'damaged',
|
'damaged',
|
||||||
'expired',
|
'expired',
|
||||||
# 'mispick',
|
# 'mispick',
|
||||||
|
@ -453,7 +531,11 @@ class ReceivingForm(colander.MappingSchema):
|
||||||
|
|
||||||
units = colander.SchemaNode(colander.Decimal(), missing=None)
|
units = colander.SchemaNode(colander.Decimal(), missing=None)
|
||||||
|
|
||||||
expiration_date = colander.SchemaNode(colander.Date(), missing=colander.null)
|
expiration_date = colander.SchemaNode(colander.Date(),
|
||||||
|
widget=dfwidget.TextInputWidget(),
|
||||||
|
missing=colander.null)
|
||||||
|
|
||||||
|
delete_row = colander.SchemaNode(colander.Boolean())
|
||||||
|
|
||||||
|
|
||||||
def includeme(config):
|
def includeme(config):
|
||||||
|
|
Loading…
Reference in a new issue