Add buefy theme support for ordering worksheet
This commit is contained in:
parent
7a01cb8873
commit
58362ae858
|
@ -4,6 +4,8 @@ const NumericInput = {
|
||||||
'<b-input',
|
'<b-input',
|
||||||
':name="name"',
|
':name="name"',
|
||||||
':value="value"',
|
':value="value"',
|
||||||
|
'@focus="focus"',
|
||||||
|
'@blur="blur"',
|
||||||
'@keydown.native="keyDown"',
|
'@keydown.native="keyDown"',
|
||||||
'@input="valueChanged"',
|
'@input="valueChanged"',
|
||||||
'>',
|
'>',
|
||||||
|
@ -18,6 +20,14 @@ const NumericInput = {
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
|
||||||
|
focus(event) {
|
||||||
|
this.$emit('focus', event)
|
||||||
|
},
|
||||||
|
|
||||||
|
blur(event) {
|
||||||
|
this.$emit('blur', event)
|
||||||
|
},
|
||||||
|
|
||||||
keyDown(event) {
|
keyDown(event) {
|
||||||
// by default we only allow numeric keys, and general navigation
|
// by default we only allow numeric keys, and general navigation
|
||||||
// keys, but we might also allow Enter key
|
// keys, but we might also allow Enter key
|
||||||
|
|
|
@ -55,9 +55,16 @@
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="leading_buttons()">
|
<%def name="leading_buttons()">
|
||||||
% if master.has_worksheet and master.allow_worksheet(batch) and request.has_perm('{}.worksheet'.format(permission_prefix)):
|
% if master.has_worksheet and master.allow_worksheet(batch) and master.has_perm('worksheet'):
|
||||||
|
% if use_buefy:
|
||||||
|
<once-button tag="a"
|
||||||
|
href="${url('{}.worksheet'.format(route_prefix), uuid=batch.uuid)}"
|
||||||
|
text="Edit as Worksheet">
|
||||||
|
</once-button>
|
||||||
|
% else:
|
||||||
<button type="button" class="load-worksheet">Edit as Worksheet</button>
|
<button type="button" class="load-worksheet">Edit as Worksheet</button>
|
||||||
% endif
|
% endif
|
||||||
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="refresh_button()">
|
<%def name="refresh_button()">
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
## -*- coding: utf-8; -*-
|
## -*- coding: utf-8; -*-
|
||||||
<%inherit file="/base.mako" />
|
<%inherit file="/page.mako" />
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
<%def name="extra_javascript()">
|
||||||
${parent.extra_javascript()}
|
${parent.extra_javascript()}
|
||||||
|
% if not use_buefy:
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
|
@ -17,6 +18,7 @@
|
||||||
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="extra_styles()">
|
<%def name="extra_styles()">
|
||||||
|
@ -41,5 +43,9 @@
|
||||||
|
|
||||||
<%def name="worksheet_grid()"></%def>
|
<%def name="worksheet_grid()"></%def>
|
||||||
|
|
||||||
|
<%def name="page_content()">
|
||||||
${self.worksheet_grid()}
|
${self.worksheet_grid()}
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
|
||||||
|
${parent.body()}
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
## -*- coding: utf-8; -*-
|
## -*- coding: utf-8; -*-
|
||||||
<%inherit file="/base.mako" />
|
<%inherit file="/batch/worksheet.mako" />
|
||||||
|
|
||||||
<%def name="title()">Ordering Worksheet</%def>
|
<%def name="title()">Ordering Worksheet</%def>
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
<%def name="extra_javascript()">
|
||||||
${parent.extra_javascript()}
|
${parent.extra_javascript()}
|
||||||
|
% if not use_buefy:
|
||||||
${h.javascript_link(request.static_url('tailbone:static/js/numeric.js'))}
|
${h.javascript_link(request.static_url('tailbone:static/js/numeric.js'))}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
@ -56,6 +57,7 @@
|
||||||
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="extra_styles()">
|
<%def name="extra_styles()">
|
||||||
|
@ -112,20 +114,164 @@
|
||||||
</style>
|
</style>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
|
||||||
<%def name="context_menu_items()">
|
<%def name="context_menu_items()">
|
||||||
<li>${h.link_to("Back to {}".format(model_title), url('ordering.view', uuid=batch.uuid))}</li>
|
<li>${h.link_to("Back to {}".format(model_title), url('ordering.view', uuid=batch.uuid))}</li>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
<%def name="extra_vendor_fields()"></%def>
|
||||||
|
|
||||||
##############################
|
<%def name="extra_count()">0</%def>
|
||||||
## page body
|
|
||||||
##############################
|
|
||||||
|
|
||||||
<ul id="context-menu">
|
<%def name="extra_th()"></%def>
|
||||||
${self.context_menu_items()}
|
|
||||||
</ul>
|
|
||||||
|
|
||||||
|
<%def name="extra_td(cost)"></%def>
|
||||||
|
|
||||||
|
<%def name="order_form_grid()">
|
||||||
|
<div class="grid">
|
||||||
|
<table class="order-form">
|
||||||
|
<% column_count = 8 + len(header_columns) + (0 if ignore_cases else 1) + int(capture(self.extra_count)) %>
|
||||||
|
% for department in sorted(six.itervalues(departments), key=lambda d: d.name if d else ''):
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="department" colspan="${column_count}">Department
|
||||||
|
% if department.number or department.name:
|
||||||
|
${department.number} ${department.name}
|
||||||
|
% else:
|
||||||
|
(N/A)
|
||||||
|
% endif
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
% for subdepartment in sorted(six.itervalues(department._order_subdepartments), key=lambda s: s.name if s else ''):
|
||||||
|
<tr>
|
||||||
|
<th class="subdepartment" colspan="${column_count}">Subdepartment
|
||||||
|
% if subdepartment.number or subdepartment.name:
|
||||||
|
${subdepartment.number} ${subdepartment.name}
|
||||||
|
% else:
|
||||||
|
(N/A)
|
||||||
|
% endif
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
% for title in header_columns:
|
||||||
|
<th>${title}</th>
|
||||||
|
% endfor
|
||||||
|
% for data in history:
|
||||||
|
<th>
|
||||||
|
% if data:
|
||||||
|
% if data['purchase']['date_received']:
|
||||||
|
Rec.<br />
|
||||||
|
${data['purchase']['date_received'].strftime('%m/%d')}
|
||||||
|
% elif data['purchase']['date_ordered']:
|
||||||
|
Ord.<br />
|
||||||
|
${data['purchase']['date_ordered'].strftime('%m/%d')}
|
||||||
|
% else:
|
||||||
|
??
|
||||||
|
% endif
|
||||||
|
% endif
|
||||||
|
</th>
|
||||||
|
% endfor
|
||||||
|
% if not ignore_cases:
|
||||||
|
<th>
|
||||||
|
${order_date.strftime('%m/%d')}<br />
|
||||||
|
Cases
|
||||||
|
</th>
|
||||||
|
% endif
|
||||||
|
<th>
|
||||||
|
${order_date.strftime('%m/%d')}<br />
|
||||||
|
Units
|
||||||
|
</th>
|
||||||
|
<th>PO Total</th>
|
||||||
|
${self.extra_th()}
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
% for i, cost in enumerate(subdepartment._order_costs, 1):
|
||||||
|
<tr data-uuid="${cost.product_uuid}" class="${'even' if i % 2 == 0 else 'odd'}"
|
||||||
|
% if use_buefy:
|
||||||
|
:class="{active: activeUUID == '${cost.uuid}'}"
|
||||||
|
% endif
|
||||||
|
>
|
||||||
|
${self.order_form_row(cost)}
|
||||||
|
% for data in history:
|
||||||
|
<td class="scratch_pad">
|
||||||
|
% if data:
|
||||||
|
<% item = data['items'].get(cost.product_uuid) %>
|
||||||
|
% if item:
|
||||||
|
% if ignore_cases:
|
||||||
|
% if item['units_received'] is not None:
|
||||||
|
${int(item['units_received'] or 0)}
|
||||||
|
% elif item['units_ordered'] is not None:
|
||||||
|
${int(item['units_ordered'] or 0)}
|
||||||
|
% endif
|
||||||
|
% else:
|
||||||
|
% if item['cases_received'] is not None or item['units_received'] is not None:
|
||||||
|
${'{} / {}'.format(int(item['cases_received'] or 0), int(item['units_received'] or 0))}
|
||||||
|
% elif item['cases_ordered'] is not None or item['units_ordered'] is not None:
|
||||||
|
${'{} / {}'.format(int(item['cases_ordered'] or 0), int(item['units_ordered'] or 0))}
|
||||||
|
% endif
|
||||||
|
% endif
|
||||||
|
% endif
|
||||||
|
% endif
|
||||||
|
</td>
|
||||||
|
% endfor
|
||||||
|
% if not ignore_cases:
|
||||||
|
<td class="current-order">
|
||||||
|
% if use_buefy:
|
||||||
|
<numeric-input v-model="worksheet.cost_${cost.uuid}_cases"
|
||||||
|
@focus="activeUUID = '${cost.uuid}'; $event.target.select()"
|
||||||
|
@blur="activeUUID = null"
|
||||||
|
@keydown.native="inputKeydown($event, '${cost.uuid}', '${cost.product_uuid}')">
|
||||||
|
</numeric-input>
|
||||||
|
% else:
|
||||||
|
${h.text('cases_ordered_{}'.format(cost.uuid), value=int(cost._batchrow.cases_ordered or 0) if cost._batchrow else None)}
|
||||||
|
% endif
|
||||||
|
</td>
|
||||||
|
% endif
|
||||||
|
<td class="current-order">
|
||||||
|
% if use_buefy:
|
||||||
|
<numeric-input v-model="worksheet.cost_${cost.uuid}_units"
|
||||||
|
@focus="activeUUID = '${cost.uuid}'; $event.target.select()"
|
||||||
|
@blur="activeUUID = null"
|
||||||
|
@keydown.native="inputKeydown($event, '${cost.uuid}', '${cost.product_uuid}')">
|
||||||
|
</numeric-input>
|
||||||
|
% else:
|
||||||
|
${h.text('units_ordered_{}'.format(cost.uuid), value=int(cost._batchrow.units_ordered or 0) if cost._batchrow else None)}
|
||||||
|
% endif
|
||||||
|
</td>
|
||||||
|
## TODO: should not fall back to po_total
|
||||||
|
% if use_buefy:
|
||||||
|
<td class="po-total">{{ worksheet.cost_${cost.uuid}_total_display }}</td>
|
||||||
|
% else:
|
||||||
|
<td class="po-total">${'${:0,.2f}'.format(cost._batchrow.po_total_calculated or cost._batchrow.po_total or 0) if cost._batchrow else ''}</td>
|
||||||
|
% endif
|
||||||
|
${self.extra_td(cost)}
|
||||||
|
</tr>
|
||||||
|
% endfor
|
||||||
|
</tbody>
|
||||||
|
% endfor
|
||||||
|
% endfor
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
<%def name="order_form_row(cost)">
|
||||||
|
<td class="upc">${get_upc(cost.product)}</td>
|
||||||
|
<td class="brand">${cost.product.brand or ''}</td>
|
||||||
|
<td class="desc">${cost.product.description} ${cost.product.size or ''}</td>
|
||||||
|
<td class="case-qty">${h.pretty_quantity(cost.case_size)} ${"LB" if cost.product.weighed else "EA"}</td>
|
||||||
|
<td class="code">${cost.code or ''}</td>
|
||||||
|
<td class="preferred">${'X' if cost.preference == 1 else ''}</td>
|
||||||
|
<td class="unit-cost">
|
||||||
|
% if cost.unit_cost is not None:
|
||||||
|
$${'{:0.2f}'.format(cost.unit_cost)}
|
||||||
|
% endif
|
||||||
|
</td>
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
<%def name="page_content()">
|
||||||
|
% if use_buefy:
|
||||||
|
<ordering-worksheet></ordering-worksheet>
|
||||||
|
% else:
|
||||||
<div class="form-wrapper">
|
<div class="form-wrapper">
|
||||||
|
|
||||||
<div class="field-wrapper">
|
<div class="field-wrapper">
|
||||||
|
@ -171,134 +317,116 @@ ${h.hidden('product_uuid')}
|
||||||
${h.hidden('cases_ordered')}
|
${h.hidden('cases_ordered')}
|
||||||
${h.hidden('units_ordered')}
|
${h.hidden('units_ordered')}
|
||||||
${h.end_form()}
|
${h.end_form()}
|
||||||
|
% endif
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
<%def name="render_this_page_template()">
|
||||||
|
${parent.render_this_page_template()}
|
||||||
|
|
||||||
##############################
|
<script type="text/x-template" id="ordering-worksheet-template">
|
||||||
## methods
|
<div>
|
||||||
##############################
|
<div class="form-wrapper">
|
||||||
|
<div class="form">
|
||||||
|
|
||||||
<%def name="extra_vendor_fields()"></%def>
|
<b-field horizontal label="Vendor">
|
||||||
|
${h.link_to(vendor, url('vendors.view', uuid=vendor.uuid))}
|
||||||
|
</b-field>
|
||||||
|
|
||||||
<%def name="extra_count()">0</%def>
|
<b-field horizontal label="Vendor Email">
|
||||||
|
<span>${vendor.email or ''}</span>
|
||||||
|
</b-field>
|
||||||
|
|
||||||
<%def name="extra_th()"></%def>
|
<b-field horizontal label="Vendor Fax">
|
||||||
|
<span>${vendor.fax_number or ''}</span>
|
||||||
|
</b-field>
|
||||||
|
|
||||||
<%def name="extra_td(cost)"></%def>
|
<b-field horizontal label="Vendor Contact">
|
||||||
|
<span>${vendor.contact or ''}</span>
|
||||||
|
</b-field>
|
||||||
|
|
||||||
<%def name="order_form_grid()">
|
<b-field horizontal label="Vendor Phone">
|
||||||
<div class="grid">
|
<span>${vendor.phone or ''}</span>
|
||||||
<table class="order-form">
|
</b-field>
|
||||||
<% column_count = 8 + len(header_columns) + (0 if ignore_cases else 1) + int(capture(self.extra_count)) %>
|
|
||||||
% for department in sorted(departments.values(), key=lambda d: d.name if d else ''):
|
${self.extra_vendor_fields()}
|
||||||
<thead>
|
|
||||||
<tr>
|
<b-field horizontal label="PO Total">
|
||||||
<th class="department" colspan="${column_count}">Department
|
<span>{{ poTotalDisplay }}</span>
|
||||||
% if department.number or department.name:
|
</b-field>
|
||||||
${department.number} ${department.name}
|
|
||||||
% else:
|
</div> <!-- form -->
|
||||||
(N/A)
|
</div><!-- form-wrapper -->
|
||||||
% endif
|
|
||||||
</th>
|
${self.order_form_grid()}
|
||||||
</tr>
|
|
||||||
% for subdepartment in sorted(department._order_subdepartments.values(), key=lambda s: s.name if s else ''):
|
|
||||||
<tr>
|
|
||||||
<th class="subdepartment" colspan="${column_count}">Subdepartment
|
|
||||||
% if subdepartment.number or subdepartment.name:
|
|
||||||
${subdepartment.number} ${subdepartment.name}
|
|
||||||
% else:
|
|
||||||
(N/A)
|
|
||||||
% endif
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
% for title in header_columns:
|
|
||||||
<th>${title}</th>
|
|
||||||
% endfor
|
|
||||||
% for data in history:
|
|
||||||
<th>
|
|
||||||
% if data:
|
|
||||||
% if data['purchase']['date_received']:
|
|
||||||
Rec.<br />
|
|
||||||
${data['purchase']['date_received'].strftime('%m/%d')}
|
|
||||||
% elif data['purchase']['date_ordered']:
|
|
||||||
Ord.<br />
|
|
||||||
${data['purchase']['date_ordered'].strftime('%m/%d')}
|
|
||||||
% else:
|
|
||||||
??
|
|
||||||
% endif
|
|
||||||
% endif
|
|
||||||
</th>
|
|
||||||
% endfor
|
|
||||||
% if not ignore_cases:
|
|
||||||
<th>
|
|
||||||
${order_date.strftime('%m/%d')}<br />
|
|
||||||
Cases
|
|
||||||
</th>
|
|
||||||
% endif
|
|
||||||
<th>
|
|
||||||
${order_date.strftime('%m/%d')}<br />
|
|
||||||
Units
|
|
||||||
</th>
|
|
||||||
<th>PO Total</th>
|
|
||||||
${self.extra_th()}
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
% for i, cost in enumerate(subdepartment._order_costs, 1):
|
|
||||||
<tr data-uuid="${cost.product_uuid}" class="${'even' if i % 2 == 0 else 'odd'}">
|
|
||||||
${self.order_form_row(cost)}
|
|
||||||
% for data in history:
|
|
||||||
<td class="scratch_pad">
|
|
||||||
% if data:
|
|
||||||
<% item = data['items'].get(cost.product_uuid) %>
|
|
||||||
% if item:
|
|
||||||
% if ignore_cases:
|
|
||||||
% if item['units_received'] is not None:
|
|
||||||
${int(item['units_received'] or 0)}
|
|
||||||
% elif item['units_ordered'] is not None:
|
|
||||||
${int(item['units_ordered'] or 0)}
|
|
||||||
% endif
|
|
||||||
% else:
|
|
||||||
% if item['cases_received'] is not None or item['units_received'] is not None:
|
|
||||||
${'{} / {}'.format(int(item['cases_received'] or 0), int(item['units_received'] or 0))}
|
|
||||||
% elif item['cases_ordered'] is not None or item['units_ordered'] is not None:
|
|
||||||
${'{} / {}'.format(int(item['cases_ordered'] or 0), int(item['units_ordered'] or 0))}
|
|
||||||
% endif
|
|
||||||
% endif
|
|
||||||
% endif
|
|
||||||
% endif
|
|
||||||
</td>
|
|
||||||
% endfor
|
|
||||||
% if not ignore_cases:
|
|
||||||
<td class="current-order">
|
|
||||||
${h.text('cases_ordered_{}'.format(cost.uuid), value=int(cost._batchrow.cases_ordered or 0) if cost._batchrow else None)}
|
|
||||||
</td>
|
|
||||||
% endif
|
|
||||||
<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>
|
|
||||||
## 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
|
|
||||||
</tbody>
|
|
||||||
% endfor
|
|
||||||
% endfor
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
|
</script>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="order_form_row(cost)">
|
<%def name="make_this_page_component()">
|
||||||
<td class="upc">${get_upc(cost.product)}</td>
|
${parent.make_this_page_component()}
|
||||||
<td class="brand">${cost.product.brand or ''}</td>
|
<script type="text/javascript">
|
||||||
<td class="desc">${cost.product.description} ${cost.product.size or ''}</td>
|
|
||||||
<td class="case-qty">${h.pretty_quantity(cost.case_size)} ${"LB" if cost.product.weighed else "EA"}</td>
|
const OrderingWorksheet = {
|
||||||
<td class="code">${cost.code or ''}</td>
|
template: '#ordering-worksheet-template',
|
||||||
<td class="preferred">${'X' if cost.preference == 1 else ''}</td>
|
data() {
|
||||||
<td class="unit-cost">
|
return {
|
||||||
% if cost.unit_cost is not None:
|
worksheet: ${json.dumps(worksheet_data)|n},
|
||||||
$${'{:0.2f}'.format(cost.unit_cost)}
|
activeUUID: null,
|
||||||
|
poTotalDisplay: "$${'{:0,.2f}'.format(batch.po_total_calculated or batch.po_total or 0)}",
|
||||||
|
submitting: false,
|
||||||
|
|
||||||
|
## TODO: should find a better way to handle CSRF token
|
||||||
|
csrftoken: ${json.dumps(request.session.get_csrf_token() or request.session.new_csrf_token())|n},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
inputKeydown(event, cost_uuid, product_uuid) {
|
||||||
|
if (event.which == 13) {
|
||||||
|
if (!this.submitting) {
|
||||||
|
this.submitting = true
|
||||||
|
|
||||||
|
let url = '${url('ordering.worksheet_update', uuid=batch.uuid)}'
|
||||||
|
|
||||||
|
let params = {
|
||||||
|
product_uuid: product_uuid,
|
||||||
|
% if not ignore_cases:
|
||||||
|
cases_ordered: this.worksheet['cost_' + cost_uuid + '_cases'],
|
||||||
% endif
|
% endif
|
||||||
</td>
|
units_ordered: this.worksheet['cost_' + cost_uuid + '_units'],
|
||||||
|
}
|
||||||
|
|
||||||
|
let headers = {
|
||||||
|
## TODO: should find a better way to handle CSRF token
|
||||||
|
'X-CSRF-TOKEN': this.csrftoken,
|
||||||
|
}
|
||||||
|
|
||||||
|
## TODO: should find a better way to handle CSRF token
|
||||||
|
this.$http.post(url, params, {headers: headers}).then(response => {
|
||||||
|
if (response.data.error) {
|
||||||
|
alert(response.data.error)
|
||||||
|
} else {
|
||||||
|
this.worksheet['cost_' + cost_uuid + '_cases'] = response.data.row_cases_ordered
|
||||||
|
this.worksheet['cost_' + cost_uuid + '_units'] = response.data.row_units_ordered
|
||||||
|
this.worksheet['cost_' + cost_uuid + '_total_display'] = response.data.row_po_total_display
|
||||||
|
this.poTotalDisplay = response.data.batch_po_total_display
|
||||||
|
}
|
||||||
|
this.submitting = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
Vue.component('ordering-worksheet', OrderingWorksheet)
|
||||||
|
|
||||||
|
</script>
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
|
|
||||||
|
##############################
|
||||||
|
## page body
|
||||||
|
##############################
|
||||||
|
|
||||||
|
${parent.body()}
|
||||||
|
|
|
@ -1514,7 +1514,8 @@ class BatchMasterView(MasterView):
|
||||||
config.add_route('{}.worksheet'.format(route_prefix), '{}/{{{}}}/worksheet'.format(url_prefix, model_key))
|
config.add_route('{}.worksheet'.format(route_prefix), '{}/{{{}}}/worksheet'.format(url_prefix, model_key))
|
||||||
config.add_view(cls, attr='worksheet', route_name='{}.worksheet'.format(route_prefix),
|
config.add_view(cls, attr='worksheet', route_name='{}.worksheet'.format(route_prefix),
|
||||||
permission='{}.worksheet'.format(permission_prefix))
|
permission='{}.worksheet'.format(permission_prefix))
|
||||||
config.add_route('{}.worksheet_update'.format(route_prefix), '{}/{{{}}}/worksheet/update'.format(url_prefix, model_key))
|
config.add_route('{}.worksheet_update'.format(route_prefix), '{}/{{{}}}/worksheet/update'.format(url_prefix, model_key),
|
||||||
|
request_method='POST')
|
||||||
config.add_view(cls, attr='worksheet_update', route_name='{}.worksheet_update'.format(route_prefix),
|
config.add_view(cls, attr='worksheet_update', route_name='{}.worksheet_update'.format(route_prefix),
|
||||||
renderer='json', permission='{}.worksheet'.format(permission_prefix))
|
renderer='json', permission='{}.worksheet'.format(permission_prefix))
|
||||||
|
|
||||||
|
|
|
@ -328,6 +328,7 @@ class PurchasingBatchView(BatchMasterView):
|
||||||
buyer_display = six.text_type(buyer)
|
buyer_display = six.text_type(buyer)
|
||||||
elif self.creating:
|
elif self.creating:
|
||||||
buyer = self.request.user.employee
|
buyer = self.request.user.employee
|
||||||
|
if buyer:
|
||||||
buyer_display = six.text_type(buyer)
|
buyer_display = six.text_type(buyer)
|
||||||
f.set_default('buyer_uuid', buyer.uuid)
|
f.set_default('buyer_uuid', buyer.uuid)
|
||||||
elif self.editing:
|
elif self.editing:
|
||||||
|
|
|
@ -27,6 +27,7 @@ Views for 'ordering' (purchasing) batches
|
||||||
from __future__ import unicode_literals, absolute_import
|
from __future__ import unicode_literals, absolute_import
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import json
|
||||||
|
|
||||||
import six
|
import six
|
||||||
import openpyxl
|
import openpyxl
|
||||||
|
@ -245,6 +246,11 @@ class OrderingBatchView(PurchasingBatchView):
|
||||||
order_date = batch.date_ordered
|
order_date = batch.date_ordered
|
||||||
if not order_date:
|
if not order_date:
|
||||||
order_date = localtime(self.rattail_config).date()
|
order_date = localtime(self.rattail_config).date()
|
||||||
|
|
||||||
|
buefy_data = None
|
||||||
|
if self.get_use_buefy():
|
||||||
|
buefy_data = self.get_worksheet_buefy_data(departments)
|
||||||
|
|
||||||
return self.render_to_response('worksheet', {
|
return self.render_to_response('worksheet', {
|
||||||
'batch': batch,
|
'batch': batch,
|
||||||
'order_date': order_date,
|
'order_date': order_date,
|
||||||
|
@ -257,8 +263,32 @@ class OrderingBatchView(PurchasingBatchView):
|
||||||
'get_upc': lambda p: p.upc.pretty() if p.upc else '',
|
'get_upc': lambda p: p.upc.pretty() if p.upc else '',
|
||||||
'header_columns': self.order_form_header_columns,
|
'header_columns': self.order_form_header_columns,
|
||||||
'ignore_cases': not self.handler.allow_cases(),
|
'ignore_cases': not self.handler.allow_cases(),
|
||||||
|
'worksheet_data': buefy_data,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
def get_worksheet_buefy_data(self, departments):
|
||||||
|
data = {}
|
||||||
|
for department in six.itervalues(departments):
|
||||||
|
for subdepartment in six.itervalues(department._order_subdepartments):
|
||||||
|
for i, cost in enumerate(subdepartment._order_costs, 1):
|
||||||
|
cases = int(cost._batchrow.cases_ordered or 0) if cost._batchrow else None
|
||||||
|
units = int(cost._batchrow.units_ordered or 0) if cost._batchrow else None
|
||||||
|
key = 'cost_{}'.format(cost.uuid)
|
||||||
|
data['{}_cases'.format(key)] = cases
|
||||||
|
data['{}_units'.format(key)] = units
|
||||||
|
|
||||||
|
total = 0
|
||||||
|
row = cost._batchrow
|
||||||
|
if row:
|
||||||
|
total = row.po_total_calculated or row.po_total or 0
|
||||||
|
if not (total or cases or units):
|
||||||
|
display = ''
|
||||||
|
else:
|
||||||
|
display = '${:0,.2f}'.format(total)
|
||||||
|
data['{}_total_display'.format(key)] = display
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
def worksheet_update(self):
|
def worksheet_update(self):
|
||||||
"""
|
"""
|
||||||
Handles AJAX requests to update the order quantities for some row
|
Handles AJAX requests to update the order quantities for some row
|
||||||
|
@ -282,21 +312,34 @@ class OrderingBatchView(PurchasingBatchView):
|
||||||
"""
|
"""
|
||||||
batch = self.get_instance()
|
batch = self.get_instance()
|
||||||
|
|
||||||
cases_ordered = self.request.POST.get('cases_ordered', '0')
|
try:
|
||||||
if not cases_ordered or not cases_ordered.isdigit():
|
data = self.request.json_body
|
||||||
return {'error': "Invalid value for cases ordered: {}".format(cases_ordered)}
|
except json.JSONDecodeError:
|
||||||
|
data = self.request.POST
|
||||||
|
|
||||||
|
cases_ordered = data.get('cases_ordered')
|
||||||
|
if cases_ordered is None:
|
||||||
|
cases_ordered = 0
|
||||||
|
elif not isinstance(cases_ordered, int):
|
||||||
|
if cases_ordered == '':
|
||||||
|
cases_ordered = 0
|
||||||
|
else:
|
||||||
cases_ordered = int(cases_ordered)
|
cases_ordered = int(cases_ordered)
|
||||||
if cases_ordered >= 100000: # TODO: really this depends on underlying column
|
if cases_ordered >= 100000: # TODO: really this depends on underlying column
|
||||||
return {'error': "Invalid value for cases ordered: {}".format(cases_ordered)}
|
return {'error': "Invalid value for cases ordered: {}".format(cases_ordered)}
|
||||||
|
|
||||||
units_ordered = self.request.POST.get('units_ordered', '0')
|
units_ordered = data.get('units_ordered')
|
||||||
if not units_ordered or not units_ordered.isdigit():
|
if units_ordered is None:
|
||||||
return {'error': "Invalid value for units ordered: {}".format(units_ordered)}
|
units_ordered = 0
|
||||||
|
elif not isinstance(units_ordered, int):
|
||||||
|
if units_ordered == '':
|
||||||
|
units_ordered = 0
|
||||||
|
else:
|
||||||
units_ordered = int(units_ordered)
|
units_ordered = int(units_ordered)
|
||||||
if units_ordered >= 100000: # TODO: really this depends on underlying column
|
if units_ordered >= 100000: # TODO: really this depends on underlying column
|
||||||
return {'error': "Invalid value for units ordered: {}".format(units_ordered)}
|
return {'error': "Invalid value for units ordered: {}".format(units_ordered)}
|
||||||
|
|
||||||
uuid = self.request.POST.get('product_uuid')
|
uuid = data.get('product_uuid')
|
||||||
product = self.Session.query(model.Product).get(uuid) if uuid else None
|
product = self.Session.query(model.Product).get(uuid) if uuid else None
|
||||||
if not product:
|
if not product:
|
||||||
return {'error': "Product not found"}
|
return {'error': "Product not found"}
|
||||||
|
@ -336,8 +379,10 @@ class OrderingBatchView(PurchasingBatchView):
|
||||||
'row_units_ordered': int(row.units_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': '${: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,
|
'row_po_total_calculated': '${:0,.2f}'.format(row.po_total_calculated or 0) if row else None,
|
||||||
|
'row_po_total_display': '${:0,.2f}'.format(row.po_total_calculated or row.po_total or 0) if row else None,
|
||||||
'batch_po_total': '${:0,.2f}'.format(batch.po_total or 0),
|
'batch_po_total': '${:0,.2f}'.format(batch.po_total or 0),
|
||||||
'batch_po_total_calculated': '${:0,.2f}'.format(batch.po_total_calculated or 0),
|
'batch_po_total_calculated': '${:0,.2f}'.format(batch.po_total_calculated or 0),
|
||||||
|
'batch_po_total_display': '${:0,.2f}'.format(batch.po_total_calculated or batch.po_total or 0),
|
||||||
}
|
}
|
||||||
|
|
||||||
def render_mobile_listitem(self, batch, i):
|
def render_mobile_listitem(self, batch, i):
|
||||||
|
|
Loading…
Reference in a new issue