Add basic configure page for Trainwreck

also the beginnings of a "yearly rollover" page which hopefully will
prove useful for helping to automate that, once i figure out how best
to go about it...
This commit is contained in:
Lance Edgar 2022-01-01 19:12:46 -06:00
parent 94883c1433
commit 3aac855fa1
6 changed files with 234 additions and 17 deletions

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2021 Lance Edgar
# Copyright © 2010-2022 Lance Edgar
#
# This file is part of Rattail.
#
@ -108,6 +108,7 @@ def before_render(event):
request = event.get('request') or threadlocal.get_current_request()
renderer_globals = event
renderer_globals['rattail_app'] = request.rattail_config.get_app()
renderer_globals['h'] = helpers
renderer_globals['url'] = request.route_url
renderer_globals['rattail'] = rattail

View file

@ -0,0 +1,31 @@
## -*- coding: utf-8; -*-
<%inherit file="/configure.mako" />
<%def name="form_content()">
<h3 class="block is-size-3">Hidden Databases</h3>
<div class="block" style="padding-left: 2rem;">
% for key, engine in six.iteritems(trainwreck_engines):
<b-field>
<b-checkbox name="hidedb_${key}"
v-model="hiddenDatabases['${key}']"
native-value="true"
@input="settingsNeedSaved = true">
${key}
</b-checkbox>
</b-field>
% endfor
</div>
</%def>
<%def name="modify_this_page_vars()">
${parent.modify_this_page_vars()}
<script type="text/javascript">
ThisPageData.hiddenDatabases = ${json.dumps(hidden_databases)|n}
</script>
</%def>
${parent.body()}

View file

@ -0,0 +1,12 @@
## -*- coding: utf-8; -*-
<%inherit file="/master/index.mako" />
<%def name="context_menu_items()">
${parent.context_menu_items()}
% if master.has_perm('rollover'):
<li>${h.link_to("Yearly Rollover", url('{}.rollover'.format(route_prefix)))}</li>
% endif
</%def>
${parent.body()}

View file

@ -0,0 +1,57 @@
## -*- coding: utf-8; -*-
<%inherit file="/page.mako" />
<%def name="title()">${index_title} &raquo; Yearly Rollover</%def>
<%def name="content_title()">Yearly Rollover</%def>
<%def name="page_content()">
<br />
% if six.text_type(next_year) not in trainwreck_engines:
<b-notification type="is-warning">
You do not have a database configured for next year (${next_year}).&nbsp;
You should be sure to configure it before next year rolls around.
</b-notification>
% endif
<p class="block">
The following Trainwreck databases are configured:
</p>
<b-table :data="engines">
<template slot-scope="props">
<b-table-column field="key" label="DB Key">
{{ props.row.key }}
</b-table-column>
<b-table-column field="oldest_date" label="Oldest Date">
<span v-if="props.row.error" class="has-text-danger">
error
</span>
<span v-if="!props.row.error">
{{ props.row.oldest_date }}
</span>
</b-table-column>
<b-table-column field="newest_date" label="Newest Date">
<span v-if="props.row.error" class="has-text-danger">
error
</span>
<span v-if="!props.row.error">
{{ props.row.newest_date }}
</span>
</b-table-column>
</template>
</b-table>
</%def>
<%def name="modify_this_page_vars()">
${parent.modify_this_page_vars()}
<script type="text/javascript">
ThisPageData.engines = ${json.dumps(engines_data)|n}
</script>
</%def>
${parent.body()}

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2021 Lance Edgar
# Copyright © 2010-2022 Lance Edgar
#
# This file is part of Rattail.
#
@ -60,6 +60,7 @@ from webob.compat import cgi_FieldStorage
from tailbone import forms, grids, diffs
from tailbone.views import View
from tailbone.db import Session
from tailbone.config import global_help_url
@ -4412,15 +4413,20 @@ class MasterView(View):
])
if names:
self.Session.query(model.Setting)\
.filter(model.Setting.name.in_(names))\
.delete(synchronize_session=False)
# nb. we do not use self.Session b/c that may not point to
# the Rattail DB for the subclass
Session().query(model.Setting)\
.filter(model.Setting.name.in_(names))\
.delete(synchronize_session=False)
def configure_save_settings(self, settings):
model = self.model
# nb. we do not use self.Session b/c that may not point to the
# Rattail DB for the subclass
session = Session()
for setting in settings:
self.Session.add(model.Setting(name=setting['name'],
value=setting['value']))
session.add(model.Setting(name=setting['name'],
value=setting['value']))
##############################
# Pyramid View Config

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2021 Lance Edgar
# Copyright © 2010-2022 Lance Edgar
#
# This file is part of Rattail.
#
@ -29,9 +29,8 @@ from __future__ import unicode_literals, absolute_import
import six
from rattail.time import localtime
from rattail.util import OrderedDict
from tailbone.db import TrainwreckSession, ExtraTrainwreckSessions
from tailbone.db import Session, TrainwreckSession, ExtraTrainwreckSessions
from tailbone.views import MasterView
@ -53,6 +52,8 @@ class TransactionView(MasterView):
SessionDefault = TrainwreckSession
SessionExtras = ExtraTrainwreckSessions
configurable = True
labels = {
'store_id': "Store",
'cashback': "Cash Back",
@ -139,13 +140,9 @@ class TransactionView(MasterView):
]
def get_db_engines(self):
engines = OrderedDict(self.rattail_config.trainwreck_engines)
hidden = self.rattail_config.getlist('tailbone', 'engines.trainwreck.hidden',
default=None)
if hidden:
for key in hidden:
engines.pop(key, None)
return engines
app = self.get_rattail_app()
trainwreck_handler = app.get_trainwreck_handler()
return trainwreck_handler.get_trainwreck_engines(include_hidden=False)
def configure_grid(self, g):
super(TransactionView, self).configure_grid(g)
@ -228,3 +225,116 @@ class TransactionView(MasterView):
f.set_type('discounted_subtotal', 'currency')
f.set_type('tax', 'currency')
f.set_type('total', 'currency')
def rollover(self):
"""
View for performing yearly rollover functions.
"""
app = self.get_rattail_app()
trainwreck_handler = app.get_trainwreck_handler()
trainwreck_engines = trainwreck_handler.get_trainwreck_engines()
current_year = app.localtime().year
# find oldest and newest dates for each database
engines_data = []
for key, engine in six.iteritems(trainwreck_engines):
if key == 'default':
session = self.Session()
else:
session = ExtraTrainwreckSessions[key]()
error = False
oldest = None
newest = None
try:
oldest = trainwreck_handler.get_oldest_transaction_date(session)
newest = trainwreck_handler.get_newest_transaction_date(session)
except:
error = True
engines_data.append({
'key': key,
'oldest_date': app.render_date(oldest) if oldest else None,
'newest_date': app.render_date(newest) if newest else None,
'error': error,
})
return self.render_to_response('rollover', {
'instance_title': "Yearly Rollover",
'trainwreck_handler': trainwreck_handler,
'current_year': current_year,
'next_year': current_year + 1,
'trainwreck_engines': trainwreck_engines,
'engines_data': engines_data,
})
def configure_get_context(self):
context = super(TransactionView, self).configure_get_context()
app = self.get_rattail_app()
trainwreck_handler = app.get_trainwreck_handler()
trainwreck_engines = trainwreck_handler.get_trainwreck_engines()
context['trainwreck_engines'] = trainwreck_engines
context['hidden_databases'] = dict([
(key, trainwreck_handler.engine_is_hidden(key))
for key in trainwreck_engines])
return context
def configure_gather_settings(self, data):
settings = super(TransactionView, self).configure_gather_settings(data)
app = self.get_rattail_app()
trainwreck_handler = app.get_trainwreck_handler()
trainwreck_engines = trainwreck_handler.get_trainwreck_engines()
hidden = []
for key in trainwreck_engines:
name = 'hidedb_{}'.format(key)
if data.get(name) == 'true':
hidden.append(key)
settings.append({'name': 'trainwreck.db.hide',
'value': ', '.join(hidden)})
return settings
def configure_remove_settings(self):
super(TransactionView, self).configure_remove_settings()
model = self.model
names = [
'trainwreck.db.hide',
'tailbone.engines.trainwreck.hidden', # deprecated
]
# nb. we do not use self.Session b/c that points to trainwreck
Session.query(model.Setting)\
.filter(model.Setting.name.in_(names))\
.delete(synchronize_session=False)
@classmethod
def defaults(cls, config):
cls._trainwreck_defaults(config)
cls._defaults(config)
@classmethod
def _trainwreck_defaults(cls, config):
route_prefix = cls.get_route_prefix()
url_prefix = cls.get_url_prefix()
permission_prefix = cls.get_permission_prefix()
model_title_plural = cls.get_model_title_plural()
# fix perm group title
config.add_tailbone_permission_group(permission_prefix,
model_title_plural)
# rollover
config.add_tailbone_permission(permission_prefix,
'{}.rollover'.format(permission_prefix),
label="Perform yearly rollover for Trainwreck")
config.add_route('{}.rollover'.format(route_prefix),
'{}/rollover'.format(url_prefix))
config.add_view(cls, attr='rollover',
route_name='{}.rollover'.format(route_prefix),
permission='{}.rollover'.format(permission_prefix))