Tweak worksheet_update()
of ordering batch view, to leverage handler
specifically this is to make use of handler's `update_row_quantity()` method, when user enters new order quantities via worksheet
This commit is contained in:
parent
c3f4a3d9ea
commit
fc830f60e8
13
docs/api/views/purchasing.ordering.rst
Normal file
13
docs/api/views/purchasing.ordering.rst
Normal file
|
@ -0,0 +1,13 @@
|
|||
|
||||
``tailbone.views.purchasing.ordering``
|
||||
======================================
|
||||
|
||||
.. automodule:: tailbone.views.purchasing.ordering
|
||||
|
||||
.. autoclass:: OrderingBatchView
|
||||
|
||||
.. autoattribute:: model_class
|
||||
|
||||
.. autoattribute:: default_handler_spec
|
||||
|
||||
.. automethod:: worksheet_update
|
|
@ -53,6 +53,7 @@ Package API:
|
|||
api/views/core
|
||||
api/views/master
|
||||
api/views/purchasing.batch
|
||||
api/views/purchasing.ordering
|
||||
|
||||
|
||||
Documentation To-Do
|
||||
|
|
|
@ -36,10 +36,16 @@
|
|||
if (data.error) {
|
||||
alert(data.error);
|
||||
} else {
|
||||
row.find('input[name^="cases_ordered_"]').val(data.row_cases_ordered);
|
||||
row.find('input[name^="units_ordered_"]').val(data.row_units_ordered);
|
||||
row.find('td.po-total').html(data.row_po_total);
|
||||
$('.po-total .field').html(data.batch_po_total);
|
||||
if (data.row_cases_ordered || data.row_units_ordered) {
|
||||
row.find('input[name^="cases_ordered_"]').val(data.row_cases_ordered);
|
||||
row.find('input[name^="units_ordered_"]').val(data.row_units_ordered);
|
||||
row.find('td.po-total').html(data.row_po_total_calculated);
|
||||
} else {
|
||||
row.find('input[name^="cases_ordered_"]').val('');
|
||||
row.find('input[name^="units_ordered_"]').val('');
|
||||
row.find('td.po-total').html('');
|
||||
}
|
||||
$('.po-total .field').html(data.batch_po_total_calculated);
|
||||
}
|
||||
submitting = false;
|
||||
});
|
||||
|
@ -151,7 +157,8 @@
|
|||
|
||||
<div class="field-wrapper po-total">
|
||||
<label>PO Total</label>
|
||||
<div class="field">$${'{:0,.2f}'.format(batch.po_total or 0)}</div>
|
||||
## TODO: should not fall back to po_total
|
||||
<div class="field">$${'{:0,.2f}'.format(batch.po_total_calculated or batch.po_total or 0)}</div>
|
||||
</div>
|
||||
|
||||
</div><!-- form-wrapper -->
|
||||
|
@ -270,7 +277,8 @@ ${h.end_form()}
|
|||
<td class="current-order">
|
||||
${h.text('units_ordered_{}'.format(cost.uuid), value=int(cost._batchrow.units_ordered or 0) if cost._batchrow else None)}
|
||||
</td>
|
||||
<td class="po-total">${'${:0,.2f}'.format(cost._batchrow.po_total or 0) if cost._batchrow else ''}</td>
|
||||
## TODO: should not fall back to po_total
|
||||
<td class="po-total">${'${:0,.2f}'.format(cost._batchrow.po_total_calculated or cost._batchrow.po_total or 0) if cost._batchrow else ''}</td>
|
||||
${self.extra_td(cost)}
|
||||
</tr>
|
||||
% endfor
|
||||
|
|
|
@ -43,7 +43,7 @@ from tailbone.views.purchasing import PurchasingBatchView
|
|||
|
||||
class OrderingBatchView(PurchasingBatchView):
|
||||
"""
|
||||
Master view for purchase order batches.
|
||||
Master view for "ordering" batches.
|
||||
"""
|
||||
route_prefix = 'ordering'
|
||||
url_prefix = '/ordering'
|
||||
|
@ -58,6 +58,33 @@ class OrderingBatchView(PurchasingBatchView):
|
|||
mobile_rows_deletable = True
|
||||
has_worksheet = True
|
||||
|
||||
labels = {
|
||||
'po_total_calculated': "PO Total",
|
||||
}
|
||||
|
||||
form_fields = [
|
||||
'id',
|
||||
'store',
|
||||
'buyer',
|
||||
'vendor',
|
||||
'department',
|
||||
'purchase',
|
||||
'vendor_email',
|
||||
'vendor_fax',
|
||||
'vendor_contact',
|
||||
'vendor_phone',
|
||||
'date_ordered',
|
||||
'po_number',
|
||||
'po_total_calculated',
|
||||
'notes',
|
||||
'created',
|
||||
'created_by',
|
||||
'status_code',
|
||||
'complete',
|
||||
'executed',
|
||||
'executed_by',
|
||||
]
|
||||
|
||||
mobile_form_fields = [
|
||||
'vendor',
|
||||
'department',
|
||||
|
@ -73,6 +100,10 @@ class OrderingBatchView(PurchasingBatchView):
|
|||
'executed_by',
|
||||
]
|
||||
|
||||
row_labels = {
|
||||
'po_total_calculated': "PO Total",
|
||||
}
|
||||
|
||||
row_grid_columns = [
|
||||
'sequence',
|
||||
'upc',
|
||||
|
@ -84,7 +115,7 @@ class OrderingBatchView(PurchasingBatchView):
|
|||
'units_ordered',
|
||||
# 'cases_received',
|
||||
# 'units_received',
|
||||
'po_total',
|
||||
'po_total_calculated',
|
||||
# 'invoice_total',
|
||||
# 'credits',
|
||||
'status_code',
|
||||
|
@ -227,7 +258,24 @@ class OrderingBatchView(PurchasingBatchView):
|
|||
|
||||
def worksheet_update(self):
|
||||
"""
|
||||
Handles AJAX requests to update current batch, from Order Form view.
|
||||
Handles AJAX requests to update the order quantities for some row
|
||||
within the current batch, from the worksheet view. POST data should
|
||||
include:
|
||||
|
||||
* ``product_uuid``
|
||||
* ``cases_ordered``
|
||||
* ``units_ordered``
|
||||
|
||||
If a row already exists for the given product, it will be updated;
|
||||
otherwise a new row is created for the product and then that is
|
||||
updated. The handler's
|
||||
:meth:`~rattail:rattail.batch.purchase.PurchaseBatchHandler.update_row_quantity()`
|
||||
method is invoked to update the row.
|
||||
|
||||
However, if both of the quantities given are empty, and a row exists
|
||||
for the given product, then that row is removed from the batch, instead
|
||||
of being updated. If a matching row is not found, it will not be
|
||||
created.
|
||||
"""
|
||||
batch = self.get_instance()
|
||||
|
||||
|
@ -250,41 +298,43 @@ class OrderingBatchView(PurchasingBatchView):
|
|||
if not product:
|
||||
return {'error': "Product not found"}
|
||||
|
||||
row = None
|
||||
rows = [r for r in batch.data_rows if r.product_uuid == uuid]
|
||||
if rows:
|
||||
assert len(rows) == 1
|
||||
row = rows[0]
|
||||
if row.po_total and not row.removed:
|
||||
batch.po_total -= row.po_total
|
||||
if cases_ordered or units_ordered:
|
||||
row.cases_ordered = cases_ordered or None
|
||||
row.units_ordered = units_ordered or None
|
||||
if row.removed:
|
||||
row.removed = False
|
||||
batch.rowcount += 1
|
||||
self.handler.refresh_row(row)
|
||||
if row.po_unit_cost:
|
||||
row.po_total = row.po_unit_cost * self.handler.get_units_ordered(row)
|
||||
batch.po_total = (batch.po_total or 0) + row.po_total
|
||||
else:
|
||||
row.removed = True
|
||||
# first we find out which existing row(s) match the given product
|
||||
matches = [row for row in batch.active_rows()
|
||||
if row.product_uuid == product.uuid]
|
||||
if matches and len(matches) != 1:
|
||||
raise RuntimeError("found too many ({}) matches for product {} in batch {}".format(
|
||||
len(matches), product.uuid, batch.uuid))
|
||||
|
||||
elif cases_ordered or units_ordered:
|
||||
row = model.PurchaseBatchRow()
|
||||
row.product = product
|
||||
row.cases_ordered = cases_ordered or None
|
||||
row.units_ordered = units_ordered or None
|
||||
self.handler.add_row(batch, row)
|
||||
if row.po_unit_cost:
|
||||
row.po_total = row.po_unit_cost * self.handler.get_units_ordered(row)
|
||||
batch.po_total = (batch.po_total or 0) + row.po_total
|
||||
row = None
|
||||
if cases_ordered or units_ordered:
|
||||
|
||||
# make a new row if necessary
|
||||
if matches:
|
||||
row = matches[0]
|
||||
else:
|
||||
row = self.handler.make_row()
|
||||
row.product = product
|
||||
self.handler.add_row(batch, row)
|
||||
|
||||
# update row quantities
|
||||
self.handler.update_row_quantity(row, cases_ordered=cases_ordered,
|
||||
units_ordered=units_ordered)
|
||||
|
||||
else: # empty order quantities
|
||||
|
||||
# remove row if present
|
||||
if matches:
|
||||
row = matches[0]
|
||||
self.handler.do_remove_row(row)
|
||||
row = None
|
||||
|
||||
return {
|
||||
'row_cases_ordered': '' if not row or row.removed else int(row.cases_ordered or 0),
|
||||
'row_units_ordered': '' if not row or row.removed else int(row.units_ordered or 0),
|
||||
'row_po_total': '' if not row or row.removed else '${:0,.2f}'.format(row.po_total or 0),
|
||||
'row_cases_ordered': int(row.cases_ordered or 0) if row else None,
|
||||
'row_units_ordered': int(row.units_ordered or 0) if row else None,
|
||||
'row_po_total': '${:0,.2f}'.format(row.po_total or 0) if row else None,
|
||||
'row_po_total_calculated': '${:0,.2f}'.format(row.po_total_calculated or 0) if row else None,
|
||||
'batch_po_total': '${:0,.2f}'.format(batch.po_total or 0),
|
||||
'batch_po_total_calculated': '${:0,.2f}'.format(batch.po_total_calculated or 0),
|
||||
}
|
||||
|
||||
def render_mobile_listitem(self, batch, i):
|
||||
|
|
Loading…
Reference in a new issue