Improve views for taxes, esp. in POS batches
This commit is contained in:
parent
eccb855d09
commit
07b1d0841e
|
@ -177,13 +177,18 @@ class GridFilter(object):
|
||||||
self.key = key
|
self.key = key
|
||||||
self.config = config
|
self.config = config
|
||||||
self.label = label or prettify(key)
|
self.label = label or prettify(key)
|
||||||
self.verbs = verbs or self.get_default_verbs()
|
|
||||||
if value_renderer:
|
if value_renderer:
|
||||||
self.set_value_renderer(value_renderer)
|
self.set_value_renderer(value_renderer)
|
||||||
elif value_enum:
|
elif value_enum:
|
||||||
self.set_choices(value_enum)
|
self.set_choices(value_enum)
|
||||||
else:
|
else:
|
||||||
self.set_value_renderer(self.value_renderer_factory)
|
self.set_value_renderer(self.value_renderer_factory)
|
||||||
|
|
||||||
|
# nb. do this after setting choices, if applicable, since that
|
||||||
|
# could change default verbs
|
||||||
|
self.verbs = verbs or self.get_default_verbs()
|
||||||
|
|
||||||
self.default_active = default_active
|
self.default_active = default_active
|
||||||
self.default_verb = default_verb
|
self.default_verb = default_verb
|
||||||
self.default_value = default_value
|
self.default_value = default_value
|
||||||
|
@ -461,6 +466,10 @@ class AlchemyStringFilter(AlchemyGridFilter):
|
||||||
"""
|
"""
|
||||||
Expose contains / does-not-contain verbs in addition to core.
|
Expose contains / does-not-contain verbs in addition to core.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
if self.choices:
|
||||||
|
return ['equal', 'not_equal', 'is_null', 'is_not_null', 'is_any']
|
||||||
|
|
||||||
return ['contains', 'does_not_contain',
|
return ['contains', 'does_not_contain',
|
||||||
'contains_any_of',
|
'contains_any_of',
|
||||||
'equal', 'not_equal', 'equal_any_of',
|
'equal', 'not_equal', 'equal_any_of',
|
||||||
|
|
13
tailbone/templates/batch/pos/view.mako
Normal file
13
tailbone/templates/batch/pos/view.mako
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
## -*- coding: utf-8; -*-
|
||||||
|
<%inherit file="/batch/view.mako" />
|
||||||
|
|
||||||
|
<%def name="modify_this_page_vars()">
|
||||||
|
${parent.modify_this_page_vars()}
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
${form.component_studly}Data.taxesData = ${json.dumps(taxes_data)|n}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</%def>
|
||||||
|
|
||||||
|
${parent.body()}
|
|
@ -26,6 +26,8 @@ Views for POS batches
|
||||||
|
|
||||||
from rattail.db.model import POSBatch, POSBatchRow
|
from rattail.db.model import POSBatch, POSBatchRow
|
||||||
|
|
||||||
|
from webhelpers2.html import HTML
|
||||||
|
|
||||||
from tailbone.views.batch import BatchMasterView
|
from tailbone.views.batch import BatchMasterView
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,7 +41,11 @@ class POSBatchView(BatchMasterView):
|
||||||
route_prefix = 'batch.pos'
|
route_prefix = 'batch.pos'
|
||||||
url_prefix = '/batch/pos'
|
url_prefix = '/batch/pos'
|
||||||
creatable = False
|
creatable = False
|
||||||
|
editable = False
|
||||||
cloneable = True
|
cloneable = True
|
||||||
|
refreshable = False
|
||||||
|
rows_deletable = False
|
||||||
|
rows_bulk_deletable = False
|
||||||
|
|
||||||
labels = {
|
labels = {
|
||||||
'terminal_id': "Terminal ID",
|
'terminal_id': "Terminal ID",
|
||||||
|
@ -66,8 +72,7 @@ class POSBatchView(BatchMasterView):
|
||||||
'params',
|
'params',
|
||||||
'rowcount',
|
'rowcount',
|
||||||
'sales_total',
|
'sales_total',
|
||||||
'tax1_total',
|
'taxes',
|
||||||
'tax2_total',
|
|
||||||
'tender_total',
|
'tender_total',
|
||||||
'balance',
|
'balance',
|
||||||
'void',
|
'void',
|
||||||
|
@ -89,6 +94,7 @@ class POSBatchView(BatchMasterView):
|
||||||
'quantity',
|
'quantity',
|
||||||
'sales_total',
|
'sales_total',
|
||||||
'tender_total',
|
'tender_total',
|
||||||
|
'tax_code',
|
||||||
'user',
|
'user',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -102,8 +108,7 @@ class POSBatchView(BatchMasterView):
|
||||||
'txn_price',
|
'txn_price',
|
||||||
'quantity',
|
'quantity',
|
||||||
'sales_total',
|
'sales_total',
|
||||||
'tax1_total',
|
'tax_code',
|
||||||
'tax2_total',
|
|
||||||
'tender_total',
|
'tender_total',
|
||||||
'tender',
|
'tender',
|
||||||
'void',
|
'void',
|
||||||
|
@ -126,8 +131,6 @@ class POSBatchView(BatchMasterView):
|
||||||
g.set_link('created_by')
|
g.set_link('created_by')
|
||||||
|
|
||||||
g.set_type('sales_total', 'currency')
|
g.set_type('sales_total', 'currency')
|
||||||
g.set_type('tax1_total', 'currency')
|
|
||||||
g.set_type('tax2_total', 'currency')
|
|
||||||
g.set_type('tender_total', 'currency')
|
g.set_type('tender_total', 'currency')
|
||||||
|
|
||||||
# executed
|
# executed
|
||||||
|
@ -149,13 +152,54 @@ class POSBatchView(BatchMasterView):
|
||||||
f.set_renderer('customer', self.render_customer)
|
f.set_renderer('customer', self.render_customer)
|
||||||
|
|
||||||
f.set_type('sales_total', 'currency')
|
f.set_type('sales_total', 'currency')
|
||||||
f.set_type('tax1_total', 'currency')
|
|
||||||
f.set_type('tax2_total', 'currency')
|
|
||||||
f.set_type('tender_total', 'currency')
|
f.set_type('tender_total', 'currency')
|
||||||
f.set_type('tender_total', 'currency')
|
f.set_type('tender_total', 'currency')
|
||||||
|
|
||||||
|
f.set_renderer('taxes', self.render_taxes)
|
||||||
|
|
||||||
f.set_renderer('balance', lambda batch, field: app.render_currency(batch.get_balance()))
|
f.set_renderer('balance', lambda batch, field: app.render_currency(batch.get_balance()))
|
||||||
|
|
||||||
|
def render_taxes(self, batch, field):
|
||||||
|
route_prefix = self.get_route_prefix()
|
||||||
|
|
||||||
|
factory = self.get_grid_factory()
|
||||||
|
g = factory(
|
||||||
|
key=f'{route_prefix}.taxes',
|
||||||
|
data=[],
|
||||||
|
columns=[
|
||||||
|
'code',
|
||||||
|
'description',
|
||||||
|
'rate',
|
||||||
|
'total',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
return HTML.literal(
|
||||||
|
g.render_buefy_table_element(data_prop='taxesData'))
|
||||||
|
|
||||||
|
def template_kwargs_view(self, **kwargs):
|
||||||
|
kwargs = super().template_kwargs_view(**kwargs)
|
||||||
|
app = self.get_rattail_app()
|
||||||
|
batch = kwargs['instance']
|
||||||
|
|
||||||
|
taxes = []
|
||||||
|
for btax in batch.taxes.values():
|
||||||
|
data = {
|
||||||
|
'uuid': btax.uuid,
|
||||||
|
'code': btax.tax_code,
|
||||||
|
'description': btax.tax.description,
|
||||||
|
'rate': app.render_percent(btax.tax_rate),
|
||||||
|
'total': app.render_currency(btax.tax_total),
|
||||||
|
}
|
||||||
|
taxes.append(data)
|
||||||
|
taxes.sort(key=lambda t: t['code'])
|
||||||
|
kwargs['taxes_data'] = taxes
|
||||||
|
|
||||||
|
kwargs['execute_enabled'] = False
|
||||||
|
kwargs['why_not_execute'] = "POS batch must be executed at POS"
|
||||||
|
|
||||||
|
return kwargs
|
||||||
|
|
||||||
def configure_row_grid(self, g):
|
def configure_row_grid(self, g):
|
||||||
super().configure_row_grid(g)
|
super().configure_row_grid(g)
|
||||||
|
|
||||||
|
|
|
@ -861,6 +861,14 @@ class MasterView(View):
|
||||||
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_tax(self, obj, field):
|
||||||
|
tax = getattr(obj, field)
|
||||||
|
if not tax:
|
||||||
|
return
|
||||||
|
text = str(tax)
|
||||||
|
url = self.request.route_url('taxes.view', uuid=tax.uuid)
|
||||||
|
return tags.link_to(text, url)
|
||||||
|
|
||||||
def render_tender(self, obj, field):
|
def render_tender(self, obj, field):
|
||||||
tender = getattr(obj, field)
|
tender = getattr(obj, field)
|
||||||
if not tender:
|
if not tender:
|
||||||
|
|
|
@ -366,6 +366,15 @@ class ProductView(MasterView):
|
||||||
g.set_renderer('cost', self.render_cost)
|
g.set_renderer('cost', self.render_cost)
|
||||||
g.set_label('cost', "Unit Cost")
|
g.set_label('cost', "Unit Cost")
|
||||||
|
|
||||||
|
# tax
|
||||||
|
g.set_joiner('tax', lambda q: q.outerjoin(model.Tax))
|
||||||
|
taxes = self.Session.query(model.Tax)\
|
||||||
|
.order_by(model.Tax.code)\
|
||||||
|
.all()
|
||||||
|
taxes = OrderedDict([(tax.uuid, tax.description)
|
||||||
|
for tax in taxes])
|
||||||
|
g.set_filter('tax', model.Tax.uuid, value_enum=taxes)
|
||||||
|
|
||||||
# report_code_name
|
# report_code_name
|
||||||
g.set_joiner('report_code_name', lambda q: q.outerjoin(model.ReportCode))
|
g.set_joiner('report_code_name', lambda q: q.outerjoin(model.ReportCode))
|
||||||
g.set_filter('report_code_name', model.ReportCode.name)
|
g.set_filter('report_code_name', model.ReportCode.name)
|
||||||
|
@ -810,7 +819,7 @@ class ProductView(MasterView):
|
||||||
raise self.notfound()
|
raise self.notfound()
|
||||||
|
|
||||||
def configure_form(self, f):
|
def configure_form(self, f):
|
||||||
super(ProductView, self).configure_form(f)
|
super().configure_form(f)
|
||||||
product = f.model_instance
|
product = f.model_instance
|
||||||
|
|
||||||
# department
|
# department
|
||||||
|
@ -934,7 +943,7 @@ class ProductView(MasterView):
|
||||||
f.set_label('tax_uuid', "Tax")
|
f.set_label('tax_uuid', "Tax")
|
||||||
else:
|
else:
|
||||||
f.set_readonly('tax')
|
f.set_readonly('tax')
|
||||||
# f.set_renderer('tax', self.render_tax)
|
f.set_renderer('tax', self.render_tax)
|
||||||
|
|
||||||
# tax1/2/3
|
# tax1/2/3
|
||||||
f.set_readonly('tax1')
|
f.set_readonly('tax1')
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
################################################################################
|
################################################################################
|
||||||
#
|
#
|
||||||
# Rattail -- Retail Software Framework
|
# Rattail -- Retail Software Framework
|
||||||
# Copyright © 2010-2022 Lance Edgar
|
# Copyright © 2010-2023 Lance Edgar
|
||||||
#
|
#
|
||||||
# This file is part of Rattail.
|
# This file is part of Rattail.
|
||||||
#
|
#
|
||||||
|
@ -24,8 +24,6 @@
|
||||||
Tax Views
|
Tax Views
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from __future__ import unicode_literals, absolute_import
|
|
||||||
|
|
||||||
from rattail.db import model
|
from rattail.db import model
|
||||||
|
|
||||||
from tailbone.views import MasterView
|
from tailbone.views import MasterView
|
||||||
|
@ -53,12 +51,26 @@ class TaxView(MasterView):
|
||||||
]
|
]
|
||||||
|
|
||||||
def configure_grid(self, g):
|
def configure_grid(self, g):
|
||||||
super(TaxView, self).configure_grid(g)
|
super().configure_grid(g)
|
||||||
g.filters['description'].default_active = True
|
|
||||||
g.filters['description'].default_verb = 'contains'
|
# code
|
||||||
g.set_sort_defaults('code')
|
g.set_sort_defaults('code')
|
||||||
g.set_link('code')
|
g.set_link('code')
|
||||||
|
|
||||||
|
# description
|
||||||
g.set_link('description')
|
g.set_link('description')
|
||||||
|
g.filters['description'].default_active = True
|
||||||
|
g.filters['description'].default_verb = 'contains'
|
||||||
|
|
||||||
|
# rate
|
||||||
|
g.set_type('rate', 'percent')
|
||||||
|
|
||||||
|
def configure_form(self, f):
|
||||||
|
super().configure_form(f)
|
||||||
|
|
||||||
|
# rate
|
||||||
|
f.set_type('rate', 'percent')
|
||||||
|
|
||||||
|
|
||||||
# TODO: deprecate / remove this
|
# TODO: deprecate / remove this
|
||||||
TaxesView = TaxView
|
TaxesView = TaxView
|
||||||
|
|
|
@ -43,6 +43,7 @@ def defaults(config, **kwargs):
|
||||||
config.include(mod('tailbone.views.reportcodes'))
|
config.include(mod('tailbone.views.reportcodes'))
|
||||||
config.include(mod('tailbone.views.stores'))
|
config.include(mod('tailbone.views.stores'))
|
||||||
config.include(mod('tailbone.views.subdepartments'))
|
config.include(mod('tailbone.views.subdepartments'))
|
||||||
|
config.include(mod('tailbone.views.taxes'))
|
||||||
config.include(mod('tailbone.views.tenders'))
|
config.include(mod('tailbone.views.tenders'))
|
||||||
config.include(mod('tailbone.views.uoms'))
|
config.include(mod('tailbone.views.uoms'))
|
||||||
config.include(mod('tailbone.views.vendors'))
|
config.include(mod('tailbone.views.vendors'))
|
||||||
|
|
Loading…
Reference in a new issue