Misc. API improvements for sake of mobile receiving
This commit is contained in:
parent
ad9c193061
commit
a721ec4a43
|
@ -107,6 +107,9 @@ class APIBatchView(APIBatchMixin, APIMasterView):
|
|||
'created_by_uuid': batch.created_by.uuid,
|
||||
'created_by_display': six.text_type(batch.created_by),
|
||||
'complete': batch.complete,
|
||||
'status_code': batch.status_code,
|
||||
'status_display': batch.STATUS.get(batch.status_code,
|
||||
six.text_type(batch.status_code)),
|
||||
'executed': executed,
|
||||
'executed_by_uuid': batch.executed_by_uuid,
|
||||
'executed_by_display': six.text_type(batch.executed_by or ''),
|
||||
|
|
|
@ -34,6 +34,7 @@ import humanize
|
|||
from rattail import pod
|
||||
from rattail.db import model
|
||||
from rattail.time import make_utc
|
||||
from rattail.util import pretty_quantity
|
||||
|
||||
from deform import widget as dfwidget
|
||||
|
||||
|
@ -54,6 +55,7 @@ class ReceivingBatchViews(APIBatchView):
|
|||
collection_url_prefix = '/receiving-batches'
|
||||
object_url_prefix = '/receiving-batch'
|
||||
supports_toggle_complete = True
|
||||
supports_execute = True
|
||||
|
||||
def base_query(self):
|
||||
query = super(ReceivingBatchViews, self).base_query()
|
||||
|
@ -69,20 +71,15 @@ class ReceivingBatchViews(APIBatchView):
|
|||
data['department_uuid'] = batch.department_uuid
|
||||
data['department_display'] = six.text_type(batch.department) if batch.department else None
|
||||
|
||||
return data
|
||||
data['po_total'] = batch.po_total
|
||||
data['invoice_total'] = batch.invoice_total
|
||||
data['invoice_total_calculated'] = batch.invoice_total_calculated
|
||||
|
||||
def get_purchase(self, uuid):
|
||||
return self.Session.query(model.Purchase).get(uuid)
|
||||
return data
|
||||
|
||||
def create_object(self, data):
|
||||
data = dict(data)
|
||||
|
||||
data['mode'] = self.enum.PURCHASE_BATCH_MODE_RECEIVING
|
||||
|
||||
# if 'purchase_key' in data:
|
||||
# purchase = self.get_purchase(data['purchase_key'])
|
||||
# data['purchase'] = purchase
|
||||
|
||||
batch = super(ReceivingBatchViews, self).create_object(data)
|
||||
return batch
|
||||
|
||||
|
@ -135,7 +132,7 @@ class ReceivingBatchViews(APIBatchView):
|
|||
elif purchase.status == self.enum.PURCHASE_STATUS_RECEIVED:
|
||||
date = purchase.date_received
|
||||
total = purchase.invoice_total
|
||||
return '{} for ${:0,.2f} ({})'.format(date, total, purchase.department or purchase.buyer)
|
||||
return '{} for ${:0,.2f} ({})'.format(date, total or 0, purchase.department or purchase.buyer)
|
||||
|
||||
@classmethod
|
||||
def defaults(cls, config):
|
||||
|
@ -241,6 +238,15 @@ class ReceivingBatchRowViews(APIBatchRowView):
|
|||
{'field': 'units_shipped', 'op': 'is_null'},
|
||||
{'field': 'units_shipped', 'op': '==', 'value': 0},
|
||||
]},
|
||||
{'or': [
|
||||
# but "unexpected" also implies we have some confirmed amount(s)
|
||||
{'field': 'cases_received', 'op': '!=', 'value': 0},
|
||||
{'field': 'units_received', 'op': '!=', 'value': 0},
|
||||
{'field': 'cases_damaged', 'op': '!=', 'value': 0},
|
||||
{'field': 'units_damaged', 'op': '!=', 'value': 0},
|
||||
{'field': 'cases_expired', 'op': '!=', 'value': 0},
|
||||
{'field': 'units_expired', 'op': '!=', 'value': 0},
|
||||
]},
|
||||
]},
|
||||
])
|
||||
|
||||
|
@ -271,6 +277,7 @@ class ReceivingBatchRowViews(APIBatchRowView):
|
|||
batch = row.batch
|
||||
data = super(ReceivingBatchRowViews, self).normalize(row)
|
||||
|
||||
data['product_uuid'] = row.product_uuid
|
||||
data['item_id'] = row.item_id
|
||||
data['upc'] = six.text_type(row.upc)
|
||||
data['upc_pretty'] = row.upc.pretty() if row.upc else None
|
||||
|
@ -304,6 +311,53 @@ class ReceivingBatchRowViews(APIBatchRowView):
|
|||
data['cases_expired'] = row.cases_expired
|
||||
data['units_expired'] = row.units_expired
|
||||
|
||||
data['po_unit_cost'] = row.po_unit_cost
|
||||
data['po_total'] = row.po_total
|
||||
|
||||
data['invoice_unit_cost'] = row.invoice_unit_cost
|
||||
data['invoice_total'] = row.invoice_total
|
||||
data['invoice_total_calculated'] = row.invoice_total_calculated
|
||||
|
||||
data['allow_cases'] = self.handler.allow_cases()
|
||||
|
||||
data['quick_receive'] = self.rattail_config.getbool(
|
||||
'rattail.batch', 'purchase.mobile_quick_receive',
|
||||
default=True)
|
||||
|
||||
if batch.order_quantities_known:
|
||||
data['quick_receive_all'] = self.rattail_config.getbool(
|
||||
'rattail.batch', 'purchase.mobile_quick_receive_all',
|
||||
default=False)
|
||||
|
||||
# TODO: this was copied from regular view receive_row() method; should merge
|
||||
if data['quick_receive'] and data.get('quick_receive_all'):
|
||||
if data['allow_cases']:
|
||||
data['quick_receive_uom'] = 'CS'
|
||||
raise NotImplementedError("TODO: add CS support for quick_receive_all")
|
||||
else:
|
||||
data['quick_receive_uom'] = data['unit_uom']
|
||||
accounted_for = self.handler.get_units_accounted_for(row)
|
||||
remainder = self.handler.get_units_ordered(row) - accounted_for
|
||||
|
||||
if accounted_for:
|
||||
# some product accounted for; button should receive "remainder" only
|
||||
if remainder:
|
||||
remainder = pretty_quantity(remainder)
|
||||
data['quick_receive_quantity'] = remainder
|
||||
data['quick_receive_text'] = "Receive Remainder ({} {})".format(
|
||||
remainder, data['unit_uom'])
|
||||
else:
|
||||
# unless there is no remainder, in which case disable it
|
||||
data['quick_receive'] = False
|
||||
|
||||
else: # nothing yet accounted for, button should receive "all"
|
||||
if not remainder:
|
||||
log.warning("quick receive remainder is empty for row %s", row.uuid)
|
||||
remainder = pretty_quantity(remainder)
|
||||
data['quick_receive_quantity'] = remainder
|
||||
data['quick_receive_text'] = "Receive ALL ({} {})".format(
|
||||
remainder, data['unit_uom'])
|
||||
|
||||
data['unexpected_alert'] = None
|
||||
if batch.order_quantities_known and not row.cases_ordered and not row.units_ordered:
|
||||
warn = True
|
||||
|
|
|
@ -285,7 +285,8 @@
|
|||
|
||||
<%def name="object_helpers()">
|
||||
${parent.object_helpers()}
|
||||
% if not request.rattail_config.production():
|
||||
## TODO: for now this is a truck-dump-only feature? maybe should change that
|
||||
% if not request.rattail_config.production() and master.allow_truck_dump:
|
||||
% if not batch.executed and not batch.complete and request.has_perm('admin'):
|
||||
% if (batch.is_truck_dump_parent() and batch.truck_dump_children_first) or not batch.is_truck_dump_related():
|
||||
<div class="object-helper">
|
||||
|
|
|
@ -130,6 +130,7 @@ class ReceivingBatchView(PurchasingBatchView):
|
|||
model_title_plural = "Receiving Batches"
|
||||
index_title = "Receiving"
|
||||
downloadable = True
|
||||
bulk_deletable = True
|
||||
rows_editable = True
|
||||
mobile_creatable = True
|
||||
mobile_rows_filterable = True
|
||||
|
@ -200,6 +201,7 @@ class ReceivingBatchView(PurchasingBatchView):
|
|||
'truck_dump_status',
|
||||
'rowcount',
|
||||
'order_quantities_known',
|
||||
'receiving_complete',
|
||||
'complete',
|
||||
'executed',
|
||||
'executed_by',
|
||||
|
@ -639,9 +641,6 @@ class ReceivingBatchView(PurchasingBatchView):
|
|||
default_value=default_status)
|
||||
return filters
|
||||
|
||||
def get_purchase(self, uuid):
|
||||
return self.Session.query(model.Purchase).get(uuid)
|
||||
|
||||
def mobile_create(self):
|
||||
"""
|
||||
Mobile view for creating a new receiving batch
|
||||
|
@ -759,9 +758,9 @@ class ReceivingBatchView(PurchasingBatchView):
|
|||
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_uuid = purchase.uuid
|
||||
purchase = self.handler.assign_purchase_order(
|
||||
batch, po_form.validated[self.purchase_order_fieldname],
|
||||
session=self.Session())
|
||||
|
||||
department = self.department_for_purchase(purchase)
|
||||
if department:
|
||||
|
|
Loading…
Reference in a new issue