Misc. improvements for ordering batches, purchases
also we now show handler's description when executing batch
This commit is contained in:
parent
e1e3301fc1
commit
fac00e6ecd
|
@ -211,6 +211,12 @@
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<section class="modal-card-body">
|
<section class="modal-card-body">
|
||||||
|
<p class="block has-text-weight-bold">
|
||||||
|
What will actually happen when this batch is executed?
|
||||||
|
</p>
|
||||||
|
<p class="block">
|
||||||
|
${handler.describe_execution(batch) or "TODO: handler does not provide a description for this batch"}
|
||||||
|
</p>
|
||||||
<${execute_form.component} ref="executeBatchForm"></${execute_form.component}>
|
<${execute_form.component} ref="executeBatchForm"></${execute_form.component}>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
## -*- coding: utf-8; -*-
|
## -*- coding: utf-8; -*-
|
||||||
|
|
||||||
<script type="text/x-template" id="${form.component}-template">
|
<script type="text/x-template" id="${form.component}-template">
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
% if not form.readonly:
|
% if not form.readonly:
|
||||||
${h.form(form.action_url, id=dform.formid, method='post', enctype='multipart/form-data', **form_kwargs)}
|
${h.form(form.action_url, id=dform.formid, method='post', enctype='multipart/form-data', **form_kwargs)}
|
||||||
|
@ -18,19 +19,24 @@
|
||||||
% elif field in dform:
|
% elif field in dform:
|
||||||
<% field = dform[field] %>
|
<% field = dform[field] %>
|
||||||
|
|
||||||
<b-field horizontal
|
% if form.field_visible(field.name):
|
||||||
label="${form.get_label(field.name)}"
|
<b-field horizontal
|
||||||
## TODO: is this class="file" really needed?
|
label="${form.get_label(field.name)}"
|
||||||
% if isinstance(field.schema.typ, deform.FileData):
|
## TODO: is this class="file" really needed?
|
||||||
class="file"
|
% if isinstance(field.schema.typ, deform.FileData):
|
||||||
% endif
|
class="file"
|
||||||
% if field.error:
|
% endif
|
||||||
type="is-danger"
|
% if field.error:
|
||||||
:message='${form.messages_json(field.error.messages())|n}'
|
type="is-danger"
|
||||||
% endif
|
:message='${form.messages_json(field.error.messages())|n}'
|
||||||
>
|
% endif
|
||||||
${field.serialize(use_buefy=True)|n}
|
>
|
||||||
</b-field>
|
${field.serialize(use_buefy=True)|n}
|
||||||
|
</b-field>
|
||||||
|
% else:
|
||||||
|
## hidden field
|
||||||
|
${field.serialize()|n}
|
||||||
|
% endif
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
% endfor
|
% endfor
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
<%def name="extra_javascript()">
|
||||||
${parent.extra_javascript()}
|
${parent.extra_javascript()}
|
||||||
|
% if not use_buefy:
|
||||||
${self.func_show_mode()}
|
${self.func_show_mode()}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
@ -56,6 +57,7 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="func_show_mode()">
|
<%def name="func_show_mode()">
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
<%def name="extra_javascript()">
|
<%def name="extra_javascript()">
|
||||||
${parent.extra_javascript()}
|
${parent.extra_javascript()}
|
||||||
|
% if not use_buefy:
|
||||||
${self.func_show_batch_type()}
|
${self.func_show_batch_type()}
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
@ -26,6 +27,7 @@
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
% endif
|
||||||
</%def>
|
</%def>
|
||||||
|
|
||||||
<%def name="func_show_batch_type()">
|
<%def name="func_show_batch_type()">
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Rattail -- Retail Software Framework
|
# Rattail -- Retail Software Framework
|
||||||
# Copyright © 2010-2018 Lance Edgar
|
# Copyright © 2010-2021 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Rattail.
|
# This file is part of Rattail.
|
||||||
#
|
#
|
||||||
|
@ -48,8 +48,12 @@ class PurchaseView(MasterView):
|
||||||
model_row_class = model.PurchaseItem
|
model_row_class = model.PurchaseItem
|
||||||
row_model_title = 'Purchase Item'
|
row_model_title = 'Purchase Item'
|
||||||
|
|
||||||
|
labels = {
|
||||||
|
'id': "ID",
|
||||||
|
}
|
||||||
|
|
||||||
grid_columns = [
|
grid_columns = [
|
||||||
'store',
|
'id',
|
||||||
'vendor',
|
'vendor',
|
||||||
'department',
|
'department',
|
||||||
'buyer',
|
'buyer',
|
||||||
|
@ -62,6 +66,7 @@ class PurchaseView(MasterView):
|
||||||
]
|
]
|
||||||
|
|
||||||
form_fields = [
|
form_fields = [
|
||||||
|
'id',
|
||||||
'store',
|
'store',
|
||||||
'vendor',
|
'vendor',
|
||||||
'department',
|
'department',
|
||||||
|
@ -162,6 +167,9 @@ class PurchaseView(MasterView):
|
||||||
default_active=True, default_verb='contains')
|
default_active=True, default_verb='contains')
|
||||||
g.sorters['buyer'] = g.make_sorter(model.Person.display_name)
|
g.sorters['buyer'] = g.make_sorter(model.Person.display_name)
|
||||||
|
|
||||||
|
# id
|
||||||
|
g.set_renderer('id', self.render_id_str)
|
||||||
|
|
||||||
# date_ordered
|
# date_ordered
|
||||||
g.filters['date_ordered'].default_active = True
|
g.filters['date_ordered'].default_active = True
|
||||||
g.filters['date_ordered'].default_verb = 'equal'
|
g.filters['date_ordered'].default_verb = 'equal'
|
||||||
|
@ -182,6 +190,9 @@ class PurchaseView(MasterView):
|
||||||
g.set_type('po_total', 'currency')
|
g.set_type('po_total', 'currency')
|
||||||
g.set_type('invoice_total', 'currency')
|
g.set_type('invoice_total', 'currency')
|
||||||
g.set_label('invoice_number', "Invoice No.")
|
g.set_label('invoice_number', "Invoice No.")
|
||||||
|
|
||||||
|
g.set_link('id')
|
||||||
|
g.set_link('vendor')
|
||||||
g.set_link('date_ordered')
|
g.set_link('date_ordered')
|
||||||
g.set_link('po_total')
|
g.set_link('po_total')
|
||||||
g.set_link('date_received')
|
g.set_link('date_received')
|
||||||
|
@ -190,6 +201,8 @@ class PurchaseView(MasterView):
|
||||||
def configure_form(self, f):
|
def configure_form(self, f):
|
||||||
super(PurchaseView, self).configure_form(f)
|
super(PurchaseView, self).configure_form(f)
|
||||||
|
|
||||||
|
f.set_renderer('id', self.render_id_str)
|
||||||
|
|
||||||
f.set_renderer('store', self.render_store)
|
f.set_renderer('store', self.render_store)
|
||||||
f.set_renderer('vendor', self.render_vendor)
|
f.set_renderer('vendor', self.render_vendor)
|
||||||
f.set_renderer('department', self.render_department)
|
f.set_renderer('department', self.render_department)
|
||||||
|
@ -220,14 +233,6 @@ class PurchaseView(MasterView):
|
||||||
url = self.request.route_url('stores.view', uuid=store.uuid)
|
url = self.request.route_url('stores.view', uuid=store.uuid)
|
||||||
return tags.link_to(text, url)
|
return tags.link_to(text, url)
|
||||||
|
|
||||||
def render_vendor(self, purchase, field):
|
|
||||||
vendor = purchase.vendor
|
|
||||||
if not vendor:
|
|
||||||
return ""
|
|
||||||
text = "({}) {}".format(vendor.id, vendor.name)
|
|
||||||
url = self.request.route_url('vendors.view', uuid=vendor.uuid)
|
|
||||||
return tags.link_to(text, url)
|
|
||||||
|
|
||||||
def render_department(self, purchase, field):
|
def render_department(self, purchase, field):
|
||||||
department = purchase.department
|
department = purchase.department
|
||||||
if not department:
|
if not department:
|
||||||
|
@ -316,6 +321,17 @@ class PurchaseView(MasterView):
|
||||||
def configure_row_form(self, f):
|
def configure_row_form(self, f):
|
||||||
super(PurchaseView, self).configure_row_form(f)
|
super(PurchaseView, self).configure_row_form(f)
|
||||||
|
|
||||||
|
# quantity fields
|
||||||
|
f.set_type('case_quantity', 'quantity')
|
||||||
|
f.set_type('cases_ordered', 'quantity')
|
||||||
|
f.set_type('units_ordered', 'quantity')
|
||||||
|
f.set_type('cases_received', 'quantity')
|
||||||
|
f.set_type('units_received', 'quantity')
|
||||||
|
f.set_type('cases_damaged', 'quantity')
|
||||||
|
f.set_type('units_damaged', 'quantity')
|
||||||
|
f.set_type('cases_expired', 'quantity')
|
||||||
|
f.set_type('units_expired', 'quantity')
|
||||||
|
|
||||||
# currency fields
|
# currency fields
|
||||||
f.set_type('po_unit_cost', 'currency')
|
f.set_type('po_unit_cost', 'currency')
|
||||||
f.set_type('po_total', 'currency')
|
f.set_type('po_total', 'currency')
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Rattail -- Retail Software Framework
|
# Rattail -- Retail Software Framework
|
||||||
# Copyright © 2010-2019 Lance Edgar
|
# Copyright © 2010-2021 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Rattail.
|
# This file is part of Rattail.
|
||||||
#
|
#
|
||||||
|
@ -180,11 +180,19 @@ class PurchaseCreditView(MasterView):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def defaults(cls, config):
|
def defaults(cls, config):
|
||||||
|
cls._purchase_credit_defaults(config)
|
||||||
|
cls._defaults(config)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _purchase_credit_defaults(cls, config):
|
||||||
route_prefix = cls.get_route_prefix()
|
route_prefix = cls.get_route_prefix()
|
||||||
url_prefix = cls.get_url_prefix()
|
url_prefix = cls.get_url_prefix()
|
||||||
permission_prefix = cls.get_permission_prefix()
|
permission_prefix = cls.get_permission_prefix()
|
||||||
model_title_plural = cls.get_model_title_plural()
|
model_title_plural = cls.get_model_title_plural()
|
||||||
|
|
||||||
|
# fix perm group name
|
||||||
|
config.add_tailbone_permission_group(permission_prefix, model_title_plural, overwrite=False)
|
||||||
|
|
||||||
# change status
|
# change status
|
||||||
config.add_tailbone_permission(permission_prefix, '{}.change_status'.format(permission_prefix),
|
config.add_tailbone_permission(permission_prefix, '{}.change_status'.format(permission_prefix),
|
||||||
"Change status for {}".format(model_title_plural))
|
"Change status for {}".format(model_title_plural))
|
||||||
|
@ -192,8 +200,6 @@ class PurchaseCreditView(MasterView):
|
||||||
config.add_view(cls, attr='change_status', route_name='{}.change_status'.format(route_prefix),
|
config.add_view(cls, attr='change_status', route_name='{}.change_status'.format(route_prefix),
|
||||||
permission='{}.change_status'.format(permission_prefix))
|
permission='{}.change_status'.format(permission_prefix))
|
||||||
|
|
||||||
cls._defaults(config)
|
|
||||||
|
|
||||||
|
|
||||||
def includeme(config):
|
def includeme(config):
|
||||||
PurchaseCreditView.defaults(config)
|
PurchaseCreditView.defaults(config)
|
||||||
|
|
|
@ -281,9 +281,9 @@ class PurchasingBatchView(BatchMasterView):
|
||||||
if self.creating:
|
if self.creating:
|
||||||
f.replace('vendor', 'vendor_uuid')
|
f.replace('vendor', 'vendor_uuid')
|
||||||
f.set_label('vendor_uuid', "Vendor")
|
f.set_label('vendor_uuid', "Vendor")
|
||||||
widget_type = self.rattail_config.get('tailbone', 'default_widget.vendor',
|
use_autocomplete = self.rattail_config.getbool(
|
||||||
default='autocomplete')
|
'rattail', 'vendor.use_autocomplete', default=True)
|
||||||
if widget_type == 'autocomplete':
|
if use_autocomplete:
|
||||||
vendor_display = ""
|
vendor_display = ""
|
||||||
if self.request.method == 'POST':
|
if self.request.method == 'POST':
|
||||||
if self.request.POST.get('vendor_uuid'):
|
if self.request.POST.get('vendor_uuid'):
|
||||||
|
@ -293,14 +293,12 @@ class PurchasingBatchView(BatchMasterView):
|
||||||
vendors_url = self.request.route_url('vendors.autocomplete')
|
vendors_url = self.request.route_url('vendors.autocomplete')
|
||||||
f.set_widget('vendor_uuid', forms.widgets.JQueryAutocompleteWidget(
|
f.set_widget('vendor_uuid', forms.widgets.JQueryAutocompleteWidget(
|
||||||
field_display=vendor_display, service_url=vendors_url))
|
field_display=vendor_display, service_url=vendors_url))
|
||||||
elif widget_type == 'dropdown':
|
else:
|
||||||
vendors = self.Session.query(model.Vendor)\
|
vendors = self.Session.query(model.Vendor)\
|
||||||
.order_by(model.Vendor.id)
|
.order_by(model.Vendor.id)
|
||||||
vendor_values = [(vendor.uuid, "({}) {}".format(vendor.id, vendor.name))
|
vendor_values = [(vendor.uuid, "({}) {}".format(vendor.id, vendor.name))
|
||||||
for vendor in vendors]
|
for vendor in vendors]
|
||||||
f.set_widget('vendor_uuid', dfwidget.SelectWidget(values=vendor_values))
|
f.set_widget('vendor_uuid', dfwidget.SelectWidget(values=vendor_values))
|
||||||
else:
|
|
||||||
raise NotImplementedError("Unsupported vendor widget type: {}".format(widget_type))
|
|
||||||
elif self.editing:
|
elif self.editing:
|
||||||
f.set_readonly('vendor')
|
f.set_readonly('vendor')
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Rattail -- Retail Software Framework
|
# Rattail -- Retail Software Framework
|
||||||
# Copyright © 2010-2020 Lance Edgar
|
# Copyright © 2010-2021 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Rattail.
|
# This file is part of Rattail.
|
||||||
#
|
#
|
||||||
|
@ -155,9 +155,11 @@ class OrderingBatchView(PurchasingBatchView):
|
||||||
|
|
||||||
def configure_form(self, f):
|
def configure_form(self, f):
|
||||||
super(OrderingBatchView, self).configure_form(f)
|
super(OrderingBatchView, self).configure_form(f)
|
||||||
|
batch = f.model_instance
|
||||||
|
|
||||||
# purchase
|
# purchase
|
||||||
f.remove_field('purchase')
|
if self.creating or not batch.executed or not batch.purchase:
|
||||||
|
f.remove_field('purchase')
|
||||||
|
|
||||||
def get_batch_kwargs(self, batch, mobile=False):
|
def get_batch_kwargs(self, batch, mobile=False):
|
||||||
kwargs = super(OrderingBatchView, self).get_batch_kwargs(batch, mobile=mobile)
|
kwargs = super(OrderingBatchView, self).get_batch_kwargs(batch, mobile=mobile)
|
||||||
|
@ -468,6 +470,11 @@ class OrderingBatchView(PurchasingBatchView):
|
||||||
|
|
||||||
return self.file_response(path)
|
return self.file_response(path)
|
||||||
|
|
||||||
|
def get_execute_success_url(self, batch, result, **kwargs):
|
||||||
|
if isinstance(result, model.Purchase):
|
||||||
|
return self.request.route_url('purchases.view', uuid=result.uuid)
|
||||||
|
return super(OrderingBatchView, self).get_execute_success_url(batch, result, **kwargs)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _ordering_defaults(cls, config):
|
def _ordering_defaults(cls, config):
|
||||||
route_prefix = cls.get_route_prefix()
|
route_prefix = cls.get_route_prefix()
|
||||||
|
|
Loading…
Reference in a new issue