Add support for more cases + units, more vendor fields, for new purchase batches
This commit is contained in:
parent
1f9a27a7ae
commit
11b4cf9616
|
@ -26,7 +26,9 @@ Vendor Field Renderers
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
from __future__ import unicode_literals, absolute_import
|
||||||
|
|
||||||
from .common import AutocompleteFieldRenderer
|
from webhelpers.html import tags
|
||||||
|
|
||||||
|
from tailbone.forms.renderers.common import AutocompleteFieldRenderer
|
||||||
|
|
||||||
|
|
||||||
class VendorFieldRenderer(AutocompleteFieldRenderer):
|
class VendorFieldRenderer(AutocompleteFieldRenderer):
|
||||||
|
@ -34,3 +36,9 @@ class VendorFieldRenderer(AutocompleteFieldRenderer):
|
||||||
Renderer for :class:`rattail.db.model.Vendor` instance fields.
|
Renderer for :class:`rattail.db.model.Vendor` instance fields.
|
||||||
"""
|
"""
|
||||||
service_route = 'vendors.autocomplete'
|
service_route = 'vendors.autocomplete'
|
||||||
|
|
||||||
|
def render_readonly(self, **kwargs):
|
||||||
|
vendor = self.raw_value
|
||||||
|
if not vendor:
|
||||||
|
return ''
|
||||||
|
return tags.link_to(vendor, self.request.route_url('vendors.view', uuid=vendor.uuid))
|
||||||
|
|
|
@ -15,17 +15,19 @@
|
||||||
}
|
}
|
||||||
if (event.which == 13) {
|
if (event.which == 13) {
|
||||||
var input = $(this);
|
var input = $(this);
|
||||||
var row = input.parents('tr:first');
|
var row = $(this).parents('tr:first');
|
||||||
var data = {
|
var data = {
|
||||||
product_uuid: row.data('uuid'),
|
product_uuid: row.data('uuid'),
|
||||||
cases_ordered: input.val() || '0'
|
cases_ordered: row.find('input[name^="cases_ordered_"]').val() || '0',
|
||||||
|
units_ordered: row.find('input[name^="units_ordered_"]').val() || '0'
|
||||||
};
|
};
|
||||||
$.post('${url('purchases.batch.order_form_update', uuid=batch.uuid)}', data, function(data) {
|
$.post('${url('purchases.batch.order_form_update', uuid=batch.uuid)}', data, function(data) {
|
||||||
if (data.error) {
|
if (data.error) {
|
||||||
alert(data.error);
|
alert(data.error);
|
||||||
} else {
|
} else {
|
||||||
input.val(data.row_cases_ordered);
|
row.find('input[name^="cases_ordered_"]').val(data.row_cases_ordered);
|
||||||
row.find('td:eq(14)').html(data.row_po_total);
|
row.find('input[name^="units_ordered_"]').val(data.row_units_ordered);
|
||||||
|
row.find('td:eq(15)').html(data.row_po_total);
|
||||||
$('.po-total .field').html(data.batch_po_total);
|
$('.po-total .field').html(data.batch_po_total);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -98,9 +100,31 @@
|
||||||
|
|
||||||
<div class="field-wrapper">
|
<div class="field-wrapper">
|
||||||
<label>Vendor</label>
|
<label>Vendor</label>
|
||||||
<div class="field">${vendor}</div>
|
<div class="field">${h.link_to(vendor, url('vendors.view', uuid=vendor.uuid))}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="field-wrapper">
|
||||||
|
<label>Vendor Email</label>
|
||||||
|
<div class="field">${vendor.email or ''}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field-wrapper">
|
||||||
|
<label>Vendor Fax</label>
|
||||||
|
<div class="field">${vendor.fax_number or ''}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field-wrapper">
|
||||||
|
<label>Vendor Contact</label>
|
||||||
|
<div class="field">${vendor.contact or ''}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="field-wrapper">
|
||||||
|
<label>Vendor Phone</label>
|
||||||
|
<div class="field">${vendor.phone or ''}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
${self.extra_vendor_fields()}
|
||||||
|
|
||||||
<div class="field-wrapper po-total">
|
<div class="field-wrapper po-total">
|
||||||
<label>PO Total</label>
|
<label>PO Total</label>
|
||||||
<div class="field">$${'{:0,.2f}'.format(batch.po_total or 0)}</div>
|
<div class="field">$${'{:0,.2f}'.format(batch.po_total or 0)}</div>
|
||||||
|
@ -111,7 +135,7 @@
|
||||||
|
|
||||||
<div class="newgrid">
|
<div class="newgrid">
|
||||||
<table class="order-form">
|
<table class="order-form">
|
||||||
<% column_count = 15 + int(capture(self.extra_count)) %>
|
<% column_count = 16 + int(capture(self.extra_count)) %>
|
||||||
% for department in sorted(departments.itervalues(), key=lambda d: d.name if d else ''):
|
% for department in sorted(departments.itervalues(), key=lambda d: d.name if d else ''):
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -132,7 +156,14 @@
|
||||||
% for data in history.itervalues():
|
% for data in history.itervalues():
|
||||||
<th>${data['purchase'].date_ordered.strftime('%m/%d') if data else ''}</th>
|
<th>${data['purchase'].date_ordered.strftime('%m/%d') if data else ''}</th>
|
||||||
% endfor
|
% endfor
|
||||||
<th>${batch.date_ordered.strftime('%m/%d')}</th>
|
<th>
|
||||||
|
${batch.date_ordered.strftime('%m/%d')}<br />
|
||||||
|
Cases
|
||||||
|
</th>
|
||||||
|
<th>
|
||||||
|
${batch.date_ordered.strftime('%m/%d')}<br />
|
||||||
|
Units
|
||||||
|
</th>
|
||||||
<th>PO Total</th>
|
<th>PO Total</th>
|
||||||
${self.extra_th()}
|
${self.extra_th()}
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -150,13 +181,17 @@
|
||||||
% for data in history.itervalues():
|
% for data in history.itervalues():
|
||||||
<td class="scratch_pad">
|
<td class="scratch_pad">
|
||||||
% if data and cost.product_uuid in data['items']:
|
% if data and cost.product_uuid in data['items']:
|
||||||
${int(data['items'][cost.product_uuid].cases_ordered or 0) or ''}
|
${'{} / {}'.format(int(data['items'][cost.product_uuid].cases_ordered or 0), int(data['items'][cost.product_uuid].units_ordered or 0))}
|
||||||
|
## ${int(data['items'][cost.product_uuid].cases_ordered or 0) or ''}
|
||||||
% endif
|
% endif
|
||||||
</td>
|
</td>
|
||||||
% endfor
|
% endfor
|
||||||
<td class="current-order">
|
<td class="current-order">
|
||||||
${h.text('cases_ordered_{}'.format(cost.uuid), value=int(cost._batchrow.cases_ordered) if cost._batchrow else None)}
|
${h.text('cases_ordered_{}'.format(cost.uuid), value=int(cost._batchrow.cases_ordered) if cost._batchrow else None)}
|
||||||
</td>
|
</td>
|
||||||
|
<td class="current-order">
|
||||||
|
${h.text('units_ordered_{}'.format(cost.uuid), value=int(cost._batchrow.units_ordered) if cost._batchrow else None)}
|
||||||
|
</td>
|
||||||
<td class="po-total">${'${:0,.2f}'.format(cost._batchrow.po_total) if cost._batchrow else ''}</td>
|
<td class="po-total">${'${:0,.2f}'.format(cost._batchrow.po_total) if cost._batchrow else ''}</td>
|
||||||
${self.extra_td(cost)}
|
${self.extra_td(cost)}
|
||||||
</tr>
|
</tr>
|
||||||
|
@ -168,6 +203,8 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<%def name="extra_vendor_fields()"></%def>
|
||||||
|
|
||||||
<%def name="extra_count()">0</%def>
|
<%def name="extra_count()">0</%def>
|
||||||
|
|
||||||
<%def name="extra_th()"></%def>
|
<%def name="extra_th()"></%def>
|
||||||
|
|
|
@ -96,12 +96,35 @@ class PurchaseBatchView(BatchMasterView):
|
||||||
fs.po_number.set(label="PO Number")
|
fs.po_number.set(label="PO Number")
|
||||||
fs.po_total.set(label="PO Total", readonly=True)
|
fs.po_total.set(label="PO Total", readonly=True)
|
||||||
|
|
||||||
|
fs.append(fa.Field('vendor_email', readonly=True,
|
||||||
|
value=lambda b: b.vendor.email.address if b.vendor.email else None))
|
||||||
|
fs.append(fa.Field('vendor_fax', readonly=True,
|
||||||
|
value=self.get_vendor_fax_number))
|
||||||
|
fs.append(fa.Field('vendor_contact', readonly=True,
|
||||||
|
value=lambda b: b.vendor.contact or None))
|
||||||
|
fs.append(fa.Field('vendor_phone', readonly=True,
|
||||||
|
value=self.get_vendor_phone_number))
|
||||||
|
|
||||||
|
def get_vendor_phone_number(self, batch):
|
||||||
|
for phone in batch.vendor.phones:
|
||||||
|
if phone.type == 'Voice':
|
||||||
|
return phone.number
|
||||||
|
|
||||||
|
def get_vendor_fax_number(self, batch):
|
||||||
|
for phone in batch.vendor.phones:
|
||||||
|
if phone.type == 'Fax':
|
||||||
|
return phone.number
|
||||||
|
|
||||||
def configure_fieldset(self, fs):
|
def configure_fieldset(self, fs):
|
||||||
fs.configure(
|
fs.configure(
|
||||||
include=[
|
include=[
|
||||||
fs.id,
|
fs.id,
|
||||||
fs.store,
|
fs.store,
|
||||||
fs.vendor,
|
fs.vendor,
|
||||||
|
fs.vendor_email,
|
||||||
|
fs.vendor_fax,
|
||||||
|
fs.vendor_contact,
|
||||||
|
fs.vendor_phone,
|
||||||
fs.buyer,
|
fs.buyer,
|
||||||
fs.date_ordered,
|
fs.date_ordered,
|
||||||
fs.po_number,
|
fs.po_number,
|
||||||
|
@ -116,6 +139,10 @@ class PurchaseBatchView(BatchMasterView):
|
||||||
if self.creating:
|
if self.creating:
|
||||||
del fs.po_total
|
del fs.po_total
|
||||||
del fs.complete
|
del fs.complete
|
||||||
|
del fs.vendor_email
|
||||||
|
del fs.vendor_fax
|
||||||
|
del fs.vendor_phone
|
||||||
|
del fs.vendor_contact
|
||||||
|
|
||||||
# default store may be configured
|
# default store may be configured
|
||||||
store = self.rattail_config.get('rattail', 'store')
|
store = self.rattail_config.get('rattail', 'store')
|
||||||
|
@ -367,10 +394,15 @@ class PurchaseBatchView(BatchMasterView):
|
||||||
"""
|
"""
|
||||||
batch = self.get_instance()
|
batch = self.get_instance()
|
||||||
|
|
||||||
quantity = self.request.POST.get('cases_ordered')
|
cases_ordered = self.request.POST.get('cases_ordered', '0')
|
||||||
if not quantity or not quantity.isdigit():
|
if not cases_ordered or not cases_ordered.isdigit():
|
||||||
return {'error': "Invalid quantity: {}".format(quantity)}
|
return {'error': "Invalid value for cases ordered: {}".format(cases_ordered)}
|
||||||
quantity = int(quantity)
|
cases_ordered = int(cases_ordered)
|
||||||
|
|
||||||
|
units_ordered = self.request.POST.get('units_ordered', '0')
|
||||||
|
if not units_ordered or not units_ordered.isdigit():
|
||||||
|
return {'error': "Invalid value for units ordered: {}".format(units_ordered)}
|
||||||
|
units_ordered = int(units_ordered)
|
||||||
|
|
||||||
uuid = self.request.POST.get('product_uuid')
|
uuid = self.request.POST.get('product_uuid')
|
||||||
product = Session.query(model.Product).get(uuid) if uuid else None
|
product = Session.query(model.Product).get(uuid) if uuid else None
|
||||||
|
@ -383,23 +415,26 @@ class PurchaseBatchView(BatchMasterView):
|
||||||
row = rows[0]
|
row = rows[0]
|
||||||
if row.po_total and not row.removed:
|
if row.po_total and not row.removed:
|
||||||
batch.po_total -= row.po_total
|
batch.po_total -= row.po_total
|
||||||
if quantity:
|
if cases_ordered or units_ordered:
|
||||||
row.cases_ordered = quantity
|
row.cases_ordered = cases_ordered
|
||||||
|
row.units_ordered = units_ordered
|
||||||
row.removed = False
|
row.removed = False
|
||||||
self.handler.refresh_row(row)
|
self.handler.refresh_row(row)
|
||||||
else:
|
else:
|
||||||
row.removed = True
|
row.removed = True
|
||||||
|
|
||||||
elif quantity:
|
elif cases_ordered or units_ordered:
|
||||||
row = model.PurchaseBatchRow()
|
row = model.PurchaseBatchRow()
|
||||||
row.sequence = max([0] + [r.sequence for r in batch.data_rows]) + 1
|
row.sequence = max([0] + [r.sequence for r in batch.data_rows]) + 1
|
||||||
row.product = product
|
row.product = product
|
||||||
batch.data_rows.append(row)
|
batch.data_rows.append(row)
|
||||||
row.cases_ordered = quantity
|
row.cases_ordered = cases_ordered
|
||||||
|
row.units_ordered = units_ordered
|
||||||
self.handler.refresh_row(row)
|
self.handler.refresh_row(row)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'row_cases_ordered': '' if row.removed else int(row.cases_ordered),
|
'row_cases_ordered': '' if row.removed else int(row.cases_ordered),
|
||||||
|
'row_units_ordered': '' if row.removed else int(row.units_ordered),
|
||||||
'row_po_total': '' if row.removed else '${:0,.2f}'.format(row.po_total),
|
'row_po_total': '' if row.removed else '${:0,.2f}'.format(row.po_total),
|
||||||
'batch_po_total': '${:0,.2f}'.format(batch.po_total),
|
'batch_po_total': '${:0,.2f}'.format(batch.po_total),
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue