Add (restore?) basic support for mobile receiving from PO
This commit is contained in:
parent
87ba8026e5
commit
34bdd2ac84
5 changed files with 122 additions and 67 deletions
|
@ -560,9 +560,11 @@ class PurchasingBatchView(BatchMasterView):
|
|||
|
||||
if self.batch_mode in (self.enum.PURCHASE_BATCH_MODE_RECEIVING,
|
||||
self.enum.PURCHASE_BATCH_MODE_COSTING):
|
||||
if batch.purchase_uuid:
|
||||
purchase = batch.purchase
|
||||
if not purchase and batch.purchase_uuid:
|
||||
purchase = self.Session.query(model.Purchase).get(batch.purchase_uuid)
|
||||
assert purchase
|
||||
if purchase:
|
||||
kwargs['purchase'] = purchase
|
||||
kwargs['buyer'] = purchase.buyer
|
||||
kwargs['buyer_uuid'] = purchase.buyer_uuid
|
||||
|
|
|
@ -66,8 +66,19 @@ class MobileItemStatusFilter(grids.filters.MobileFilter):
|
|||
|
||||
# TODO: is this accurate (enough) ?
|
||||
if value == 'incomplete':
|
||||
return query.filter(sa.or_(model.PurchaseBatchRow.cases_ordered != 0, model.PurchaseBatchRow.units_ordered != 0))\
|
||||
.filter(model.PurchaseBatchRow.status_code != model.PurchaseBatchRow.STATUS_OK)
|
||||
return query.filter(sa.or_(model.PurchaseBatchRow.cases_ordered != 0,
|
||||
model.PurchaseBatchRow.units_ordered != 0))\
|
||||
.filter(~model.PurchaseBatchRow.status_code.in_((
|
||||
model.PurchaseBatchRow.STATUS_OK,
|
||||
model.PurchaseBatchRow.STATUS_PRODUCT_NOT_FOUND)))
|
||||
|
||||
if value == 'invalid':
|
||||
return query.filter(model.PurchaseBatchRow.status_code.in_((
|
||||
model.PurchaseBatchRow.STATUS_PRODUCT_NOT_FOUND,
|
||||
model.PurchaseBatchRow.STATUS_COST_NOT_FOUND,
|
||||
model.PurchaseBatchRow.STATUS_CASE_QUANTITY_UNKNOWN,
|
||||
model.PurchaseBatchRow.STATUS_CASE_QUANTITY_DIFFERS,
|
||||
)))
|
||||
|
||||
if value == 'unexpected':
|
||||
return query.filter(sa.and_(
|
||||
|
@ -118,6 +129,8 @@ class ReceivingBatchView(PurchasingBatchView):
|
|||
|
||||
default_uom_is_case = True
|
||||
|
||||
purchase_order_fieldname = 'purchase'
|
||||
|
||||
labels = {
|
||||
'truck_dump_batch': "Truck Dump Parent",
|
||||
'invoice_parser_key': "Invoice Parser",
|
||||
|
@ -363,18 +376,7 @@ class ReceivingBatchView(PurchasingBatchView):
|
|||
|
||||
def get_batch_kwargs(self, batch, mobile=False):
|
||||
kwargs = super(ReceivingBatchView, self).get_batch_kwargs(batch, mobile=mobile)
|
||||
|
||||
if mobile:
|
||||
if 'purchase' in self.request.POST:
|
||||
purchase = self.get_purchase(self.request.POST['purchase'])
|
||||
if isinstance(purchase, model.Purchase):
|
||||
kwargs['purchase'] = purchase
|
||||
|
||||
department = self.department_for_purchase(purchase)
|
||||
if department:
|
||||
kwargs['department'] = department
|
||||
|
||||
else: # not mobile
|
||||
if not mobile:
|
||||
batch_type = self.request.POST['batch_type']
|
||||
if batch_type == 'from_scratch':
|
||||
kwargs.pop('truck_dump_batch', None)
|
||||
|
@ -516,10 +518,10 @@ class ReceivingBatchView(PurchasingBatchView):
|
|||
|
||||
# visible filter options will depend on whether batch came from purchase
|
||||
if batch.order_quantities_known:
|
||||
value_choices = ['incomplete', 'unexpected', 'damaged', 'expired', 'all']
|
||||
value_choices = ['incomplete', 'unexpected', 'damaged', 'expired', 'invalid', 'all']
|
||||
default_status = 'incomplete'
|
||||
else:
|
||||
value_choices = ['received', 'damaged', 'expired', 'all']
|
||||
value_choices = ['received', 'damaged', 'expired', 'invalid', 'all']
|
||||
default_status = 'all'
|
||||
|
||||
# remove 'expired' filter option if not relevant
|
||||
|
@ -540,10 +542,12 @@ class ReceivingBatchView(PurchasingBatchView):
|
|||
"""
|
||||
mode = self.batch_mode
|
||||
data = {'mode': mode}
|
||||
phase = 1
|
||||
|
||||
schema = MobileNewReceivingBatch().bind(session=self.Session())
|
||||
form = forms.Form(schema=schema, request=self.request)
|
||||
if form.validate(newstyle=True):
|
||||
phase = form.validated['phase']
|
||||
|
||||
if form.validated['workflow'] == 'from_scratch':
|
||||
if not self.allow_from_scratch:
|
||||
|
@ -556,7 +560,7 @@ class ReceivingBatchView(PurchasingBatchView):
|
|||
batch.date_received = localtime(self.rattail_config).date()
|
||||
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))
|
||||
return self.redirect(self.get_action_url('view', batch, mobile=True))
|
||||
|
||||
elif form.validated['workflow'] == 'truck_dump':
|
||||
if not self.allow_truck_dump:
|
||||
|
@ -565,44 +569,85 @@ class ReceivingBatchView(PurchasingBatchView):
|
|||
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.vendor = self.Session.query(model.Vendor).get(form.validated['vendor'])
|
||||
batch.created_by = self.request.user
|
||||
batch.date_received = localtime(self.rattail_config).date()
|
||||
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))
|
||||
return self.redirect(self.get_action_url('view', batch, mobile=True))
|
||||
|
||||
else:
|
||||
raise NotImplementedError("Requested workflow not supported: {}".format(form.validated['workflow']))
|
||||
elif form.validated['workflow'] == 'from_po':
|
||||
if not self.allow_from_po:
|
||||
raise NotImplementedError("Requested workflow not supported: from_po")
|
||||
|
||||
vendor = None
|
||||
if self.request.method == 'POST' and self.request.POST.get('vendor'):
|
||||
vendor = self.Session.query(model.Vendor).get(self.request.POST['vendor'])
|
||||
if vendor:
|
||||
vendor = self.Session.query(model.Vendor).get(form.validated['vendor'])
|
||||
data['vendor'] = vendor
|
||||
|
||||
if self.request.POST.get('purchase'):
|
||||
purchase = self.get_purchase(self.request.POST['purchase'])
|
||||
if purchase:
|
||||
|
||||
schema = self.make_mobile_receiving_from_po_schema()
|
||||
po_form = forms.Form(schema=schema, request=self.request)
|
||||
if phase == 2:
|
||||
if po_form.validate(newstyle=True):
|
||||
batch = self.model_class()
|
||||
batch.store = self.rattail_config.get_store(self.Session())
|
||||
batch.mode = mode
|
||||
batch.vendor = vendor
|
||||
batch.store = self.rattail_config.get_store(self.Session())
|
||||
batch.buyer = self.request.user.employee
|
||||
batch.created_by = self.request.user
|
||||
batch.date_received = localtime(self.rattail_config).date()
|
||||
self.assign_purchase_order(batch, po_form)
|
||||
kwargs = self.get_batch_kwargs(batch, mobile=True)
|
||||
batch = self.handler.make_batch(self.Session(), **kwargs)
|
||||
if self.handler.should_populate(batch):
|
||||
self.handler.populate(batch)
|
||||
return self.redirect(self.request.route_url('mobile.receiving.view', uuid=batch.uuid))
|
||||
return self.redirect(self.get_action_url('view', batch, mobile=True))
|
||||
|
||||
else:
|
||||
phase = 2
|
||||
|
||||
else:
|
||||
raise NotImplementedError("Requested workflow not supported: {}".format(form.validated['workflow']))
|
||||
|
||||
data['form'] = form
|
||||
data['dform'] = form.make_deform_form()
|
||||
data['mode_title'] = self.enum.PURCHASE_BATCH_MODE[mode].capitalize()
|
||||
if vendor:
|
||||
data['phase'] = phase
|
||||
if phase == 2:
|
||||
purchases = self.eligible_purchases(vendor.uuid, mode=mode)
|
||||
data['purchases'] = [(p['key'], p['display']) for p in purchases['purchases']]
|
||||
data['purchase_order_fieldname'] = self.purchase_order_fieldname
|
||||
return self.render_to_response('create', data, mobile=True)
|
||||
|
||||
def make_mobile_receiving_from_po_schema(self):
|
||||
schema = colander.MappingSchema()
|
||||
schema.add(colander.SchemaNode(colander.String(),
|
||||
name=self.purchase_order_fieldname,
|
||||
validator=self.validate_purchase))
|
||||
return schema.bind(session=self.Session())
|
||||
|
||||
@staticmethod
|
||||
@colander.deferred
|
||||
def validate_purchase(node, kw):
|
||||
session = kw['session']
|
||||
def validate(node, value):
|
||||
purchase = session.query(model.Purchase).get(value)
|
||||
if not purchase:
|
||||
raise colander.Invalid(node, "Purchase not found")
|
||||
return purchase.uuid
|
||||
return validate
|
||||
|
||||
def assign_purchase_order(self, batch, po_form):
|
||||
"""
|
||||
Assign the original purchase order to the given batch. Default
|
||||
behavior assumes a Rattail Purchase object is what we're after.
|
||||
"""
|
||||
purchase = self.get_purchase(po_form.validated[self.purchase_order_fieldname])
|
||||
if isinstance(purchase, model.Purchase):
|
||||
batch.purchase = purchase
|
||||
|
||||
department = self.department_for_purchase(purchase)
|
||||
if department:
|
||||
batch.department = department
|
||||
|
||||
def configure_mobile_form(self, f):
|
||||
super(ReceivingBatchView, self).configure_mobile_form(f)
|
||||
batch = f.model_instance
|
||||
|
@ -950,6 +995,13 @@ class MobileNewReceivingBatch(colander.MappingSchema):
|
|||
'truck_dump',
|
||||
]))
|
||||
|
||||
phase = colander.SchemaNode(colander.Int())
|
||||
|
||||
|
||||
class MobileNewReceivingFromPO(colander.MappingSchema):
|
||||
|
||||
purchase = colander.SchemaNode(colander.String())
|
||||
|
||||
|
||||
# TODO: this is a stopgap measure to fix an obvious bug, which exists when the
|
||||
# session is not provided by the view at runtime (i.e. when it was instead
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue