Remove several references to "buefy" name

class methods, template filenames, etc.

also made various edits per newer conventions
This commit is contained in:
Lance Edgar 2024-04-14 19:54:29 -05:00
parent 96ba039299
commit c036932ce4
50 changed files with 373 additions and 361 deletions

View file

@ -33,10 +33,9 @@ from collections import OrderedDict
import sqlalchemy as sa
from sqlalchemy import orm
from sqlalchemy.ext.associationproxy import AssociationProxy, ASSOCIATION_PROXY
from wuttjamaican.util import UNSPECIFIED
from rattail.time import localtime
from rattail.util import prettify, pretty_boolean, pretty_quantity
from rattail.core import UNSPECIFIED
from rattail.util import prettify, pretty_boolean
from rattail.db.util import get_fieldnames
import colander
@ -50,10 +49,10 @@ from webhelpers2.html import tags, HTML
from tailbone.db import Session
from tailbone.util import raw_datetime, get_form_data, render_markdown
from . import types
from .widgets import (ReadonlyWidget, PlainDateWidget,
JQueryDateWidget, JQueryTimeWidget,
MultiFileUploadWidget)
from tailbone.forms import types
from tailbone.forms.widgets import (ReadonlyWidget, PlainDateWidget,
JQueryDateWidget, JQueryTimeWidget,
MultiFileUploadWidget)
from tailbone.exceptions import TailboneJSONFieldError
@ -225,7 +224,7 @@ class CustomSchemaNode(SQLAlchemySchemaNode):
if excludes:
overrides['excludes'] = excludes
return super(CustomSchemaNode, self).get_schema_from_relationship(prop, overrides)
return super().get_schema_from_relationship(prop, overrides)
def dictify(self, obj):
""" Return a dictified version of `obj` using schema information.
@ -234,7 +233,7 @@ class CustomSchemaNode(SQLAlchemySchemaNode):
This method was copied from upstream and modified to add automatic
handling of "association proxy" fields.
"""
dict_ = super(CustomSchemaNode, self).dictify(obj)
dict_ = super().dictify(obj)
for node in self:
name = node.name
@ -967,7 +966,7 @@ class Form(object):
kwargs.setdefault(':configure-fields-help', 'configureFieldsHelp')
return HTML.tag(self.component, **kwargs)
def render_buefy_field(self, fieldname, bfield_attrs={}):
def render_field_complete(self, fieldname, bfield_attrs={}):
"""
Render the given field in a Buefy-compatible way. Note that
this is meant to render *editable* fields, i.e. showing a
@ -1131,7 +1130,8 @@ class Form(object):
value = self.obtain_value(record, field_name)
if value is None:
return ""
value = localtime(self.request.rattail_config, value)
app = self.get_rattail_app()
value = app.localtime(value)
return raw_datetime(self.request.rattail_config, value)
def render_duration(self, record, field_name):
@ -1160,7 +1160,8 @@ class Form(object):
value = self.obtain_value(obj, field)
if value is None:
return ""
return pretty_quantity(value)
app = self.get_rattail_app()
return app.render_quantity(value)
def render_percent(self, obj, field):
app = self.request.rattail_config.get_app()

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2023 Lance Edgar
# Copyright © 2010-2024 Lance Edgar
#
# This file is part of Rattail.
#
@ -153,6 +153,7 @@ class DynamicCheckboxWidget(dfwidget.CheckboxWidget):
template = 'checkbox_dynamic'
# TODO: deprecate / remove this
class PlainSelectWidget(dfwidget.SelectWidget):
template = 'select_plain'

View file

@ -1339,10 +1339,10 @@ class Grid(object):
includes the context menu items and grid tools.
"""
if 'grid_columns' not in kwargs:
kwargs['grid_columns'] = self.get_buefy_columns()
kwargs['grid_columns'] = self.get_table_columns()
if 'grid_data' not in kwargs:
kwargs['grid_data'] = self.get_buefy_data()
kwargs['grid_data'] = self.get_table_data()
if 'static_data' not in kwargs:
kwargs['static_data'] = self.has_static_data()
@ -1364,10 +1364,11 @@ class Grid(object):
warnings.warn("Grid.render_buefy() is deprecated; "
"please use Grid.render_complete() instead",
DeprecationWarning, stacklevel=2)
return self.render_complete(**kwargs)
def render_buefy_table_element(self, template='/grids/b-table.mako',
data_prop='gridData', empty_labels=False,
**kwargs):
def render_table_element(self, template='/grids/b-table.mako',
data_prop='gridData', empty_labels=False,
**kwargs):
"""
This is intended for ad-hoc "small" grids with static data. Renders
just a ``<b-table>`` element instead of the typical "full" grid.
@ -1377,7 +1378,7 @@ class Grid(object):
context['data_prop'] = data_prop
context['empty_labels'] = empty_labels
if 'grid_columns' not in context:
context['grid_columns'] = self.get_buefy_columns()
context['grid_columns'] = self.get_table_columns()
context.setdefault('paginated', False)
if context['paginated']:
context.setdefault('per_page', 20)
@ -1572,10 +1573,10 @@ class Grid(object):
return True
return False
def get_buefy_columns(self):
def get_table_columns(self):
"""
Return a list of dicts representing all grid columns. Meant for use
with Buefy table.
Return a list of dicts representing all grid columns. Meant
for use with the client-side JS table.
"""
columns = []
for name in self.columns:
@ -1597,9 +1598,10 @@ class Grid(object):
if hasattr(rowobj, 'uuid'):
return rowobj.uuid
def get_buefy_data(self):
def get_table_data(self):
"""
Returns a list of data rows for the grid, for use with Buefy table.
Returns a list of data rows for the grid, for use with
client-side JS table.
"""
# filter / sort / paginate to get "visible" data
raw_data = self.make_visible_data()
@ -1635,8 +1637,8 @@ class Grid(object):
# instance, when the "display" version is different than raw data.
# here is the hack we use for that.
columns = list(self.columns)
if hasattr(self, 'buefy_data_columns'):
columns.extend(self.buefy_data_columns)
if hasattr(self, 'raw_data_columns'):
columns.extend(self.raw_data_columns)
# iterate over data fields
for name in columns:

View file

@ -154,7 +154,7 @@
${parent.modify_this_page_vars()}
<script type="text/javascript">
ThisPageData.groups = ${json.dumps(buefy_data)|n}
ThisPageData.groups = ${json.dumps(settings_data)|n}
ThisPageData.showingGroup = ${json.dumps(current_group or '')|n}
</script>

View file

@ -68,7 +68,7 @@
% endif
</%def>
<%def name="render_buefy_form()">
<%def name="render_form()">
<div class="form">
<tailbone-form></tailbone-form>
<br />

View file

@ -34,7 +34,7 @@
</nav>
</%def>
<%def name="render_form()">
<%def name="render_form_template()">
<script type="text/x-template" id="${form.component}-template">
<div class="product-info">

View file

@ -1,7 +1,7 @@
## -*- coding: utf-8; -*-
<%inherit file="/master/view_row.mako" />
<%def name="render_buefy_form()">
<%def name="render_form()">
<div class="form">
<tailbone-form></tailbone-form>
<br />

View file

@ -148,7 +148,7 @@
</div>
</%def>
<%def name="render_form()">
<%def name="render_form_template()">
## TODO: should use self.render_form_buttons()
## ${form.render_deform(form_id='batch-form', buttons=capture(self.render_form_buttons))|n}
${form.render_deform(form_id='batch-form', buttons=capture(buttons))|n}
@ -206,7 +206,7 @@
% endif
</%def>
<%def name="render_buefy_form()">
<%def name="render_form()">
<div class="form">
<${form.component} @show-upload="showUploadDialog = true">
</${form.component}>

View file

@ -9,7 +9,7 @@
% endif
</%def>
<%def name="render_buefy_form()">
<%def name="render_form()">
<div class="form">
<tailbone-form @detach-person="detachPerson">
</tailbone-form>

View file

@ -1,7 +1,7 @@
## -*- coding: utf-8; -*-
<%inherit file="/master/view.mako" />
<%def name="render_buefy_form()">
<%def name="render_form()">
<div class="form">
<${form.component} ref="mainForm"
% if master.has_perm('confirm_price'):

View file

@ -5,11 +5,11 @@
<%def name="render_form_buttons()"></%def>
<%def name="render_form()">
<%def name="render_form_template()">
${form.render_deform(buttons=capture(self.render_form_buttons))|n}
</%def>
<%def name="render_buefy_form()">
<%def name="render_form()">
<div class="form">
${form.render_vuejs_component()}
</div>
@ -18,7 +18,7 @@
<%def name="page_content()">
<div class="form-wrapper">
<br />
${self.render_buefy_form()}
${self.render_form()}
</div>
</%def>
@ -49,7 +49,7 @@
<%def name="render_this_page_template()">
% if form is not Undefined:
${self.render_form()}
${self.render_form_template()}
% endif
${parent.render_this_page_template()}
</%def>

View file

@ -18,7 +18,7 @@
<div class="panel-block">
<div>
% for field in form.grouping[group]:
${form.render_buefy_field(field)}
${form.render_field_complete(field)}
% endfor
</div>
</div>
@ -26,7 +26,7 @@
% endfor
% else:
% for field in form.fields:
${form.render_buefy_field(field)}
${form.render_field_complete(field)}
% endfor
% endif
</section>

View file

@ -1,7 +0,0 @@
## -*- coding: utf-8; -*-
## TODO: deprecate / remove this
## (tried to add deprecation warning here but it didn't seem to work)
<%def name="render_buefy_field(field, bfield_kwargs={})">
${form.render_buefy_field(field.name, bfield_attrs=bfield_kwargs)}
</%def>

View file

@ -3,12 +3,12 @@
<%def name="title()">Clone ${model_title}: ${instance_title}</%def>
<%def name="render_buefy_form()">
<%def name="render_form()">
<br />
<b-notification :closable="false">
You are about to clone the following ${model_title} as a new record:
</b-notification>
${parent.render_buefy_form()}
${parent.render_form()}
</%def>
<%def name="render_form_buttons()">

View file

@ -3,12 +3,12 @@
<%def name="title()">Delete ${model_title}: ${instance_title}</%def>
<%def name="render_buefy_form()">
<%def name="render_form()">
<br />
<b-notification type="is-danger" :closable="false">
You are about to delete the following ${model_title} and all associated data:
</b-notification>
${parent.render_buefy_form()}
${parent.render_form()}
</%def>
<%def name="render_form_buttons()">

View file

@ -7,7 +7,7 @@
${view_profiles_helper([instance])}
</%def>
<%def name="render_buefy_form()">
<%def name="render_form()">
<div class="form">
<tailbone-form v-on:make-user="makeUser"></tailbone-form>
</div>

View file

@ -1403,10 +1403,10 @@
% if request.has_perm('people_profile.view_versions'):
${revisions_grid.render_buefy_table_element(data_prop='revisions',
show_footer=True,
vshow='viewingHistory',
loading='gettingRevisions')|n}
${revisions_grid.render_table_element(data_prop='revisions',
show_footer=True,
vshow='viewingHistory',
loading='gettingRevisions')|n}
<b-modal :active.sync="showingRevisionDialog">

View file

@ -95,8 +95,8 @@
${parent.modify_this_page_vars()}
<script type="text/javascript">
ThisPageData.permissionGroups = ${json.dumps(buefy_perms)|n}
ThisPageData.sortedGroups = ${json.dumps(buefy_sorted_groups)|n}
ThisPageData.permissionGroups = ${json.dumps(perms_data)|n}
ThisPageData.sortedGroups = ${json.dumps(sorted_groups_data)|n}
</script>
</%def>
@ -113,7 +113,7 @@
},
data() {
return {
groupPermissions: ${json.dumps(buefy_perms.get(selected_group, {}).get('permissions', []))|n},
groupPermissions: ${json.dumps(perms_data.get(selected_group, {}).get('permissions', []))|n},
permissionGroupTerm: '',
permissionTerm: '',
selectedGroup: ${json.dumps(selected_group)|n},

View file

@ -54,7 +54,7 @@
${h.end_form()}
</%def>
<%def name="render_form()">
<%def name="render_form_template()">
<script type="text/x-template" id="${form.component}-template">
${self.render_form_innards()}
</script>

View file

@ -108,7 +108,7 @@
</%def>
<%def name="lookup_codes_grid()">
${lookup_codes['grid'].render_buefy_table_element(data_prop='lookupCodesData')|n}
${lookup_codes['grid'].render_table_element(data_prop='lookupCodesData')|n}
</%def>
<%def name="lookup_codes_panel()">
@ -121,7 +121,7 @@
</%def>
<%def name="sources_grid()">
${vendor_sources['grid'].render_buefy_table_element(data_prop='vendorSourcesData')|n}
${vendor_sources['grid'].render_table_element(data_prop='vendorSourcesData')|n}
</%def>
<%def name="sources_panel()">
@ -175,7 +175,7 @@
</p>
</header>
<section class="modal-card-body">
${regular_price_history_grid.render_buefy_table_element(data_prop='regularPriceHistoryData', loading='regularPriceHistoryLoading', paginated=True, per_page=10)|n}
${regular_price_history_grid.render_table_element(data_prop='regularPriceHistoryData', loading='regularPriceHistoryLoading', paginated=True, per_page=10)|n}
</section>
<footer class="modal-card-foot">
<b-button @click="showingPriceHistory_regular = false">
@ -194,7 +194,7 @@
</p>
</header>
<section class="modal-card-body">
${current_price_history_grid.render_buefy_table_element(data_prop='currentPriceHistoryData', loading='currentPriceHistoryLoading', paginated=True, per_page=10)|n}
${current_price_history_grid.render_table_element(data_prop='currentPriceHistoryData', loading='currentPriceHistoryLoading', paginated=True, per_page=10)|n}
</section>
<footer class="modal-card-foot">
<b-button @click="showingPriceHistory_current = false">
@ -213,7 +213,7 @@
</p>
</header>
<section class="modal-card-body">
${suggested_price_history_grid.render_buefy_table_element(data_prop='suggestedPriceHistoryData', loading='suggestedPriceHistoryLoading', paginated=True, per_page=10)|n}
${suggested_price_history_grid.render_table_element(data_prop='suggestedPriceHistoryData', loading='suggestedPriceHistoryLoading', paginated=True, per_page=10)|n}
</section>
<footer class="modal-card-foot">
<b-button @click="showingPriceHistory_suggested = false">
@ -232,7 +232,7 @@
</p>
</header>
<section class="modal-card-body">
${cost_history_grid.render_buefy_table_element(data_prop='costHistoryData', loading='costHistoryLoading', paginated=True, per_page=10)|n}
${cost_history_grid.render_table_element(data_prop='costHistoryData', loading='costHistoryLoading', paginated=True, per_page=10)|n}
</section>
<footer class="modal-card-foot">
<b-button @click="showingCostHistory = false">
@ -289,7 +289,7 @@
% if request.rattail_config.versioning_enabled() and master.has_perm('versions'):
ThisPageData.showingPriceHistory_regular = false
ThisPageData.regularPriceHistoryDataRaw = ${json.dumps(regular_price_history_grid.get_buefy_data()['data'])|n}
ThisPageData.regularPriceHistoryDataRaw = ${json.dumps(regular_price_history_grid.get_table_data()['data'])|n}
ThisPageData.regularPriceHistoryLoading = false
ThisPage.computed.regularPriceHistoryData = function() {
@ -318,7 +318,7 @@
}
ThisPageData.showingPriceHistory_current = false
ThisPageData.currentPriceHistoryDataRaw = ${json.dumps(current_price_history_grid.get_buefy_data()['data'])|n}
ThisPageData.currentPriceHistoryDataRaw = ${json.dumps(current_price_history_grid.get_table_data()['data'])|n}
ThisPageData.currentPriceHistoryLoading = false
ThisPage.computed.currentPriceHistoryData = function() {
@ -348,7 +348,7 @@
}
ThisPageData.showingPriceHistory_suggested = false
ThisPageData.suggestedPriceHistoryDataRaw = ${json.dumps(suggested_price_history_grid.get_buefy_data()['data'])|n}
ThisPageData.suggestedPriceHistoryDataRaw = ${json.dumps(suggested_price_history_grid.get_table_data()['data'])|n}
ThisPageData.suggestedPriceHistoryLoading = false
ThisPage.computed.suggestedPriceHistoryData = function() {
@ -377,7 +377,7 @@
}
ThisPageData.showingCostHistory = false
ThisPageData.costHistoryDataRaw = ${json.dumps(cost_history_grid.get_buefy_data()['data'])|n}
ThisPageData.costHistoryDataRaw = ${json.dumps(cost_history_grid.get_table_data()['data'])|n}
ThisPageData.costHistoryLoading = false
ThisPage.computed.costHistoryData = function() {

View file

@ -1,6 +1,5 @@
## -*- coding: utf-8; -*-
<%inherit file="/form.mako" />
<%namespace file="/forms/util.mako" import="render_buefy_field" />
<%def name="title()">Declare Credit for Row #${row.sequence}</%def>
@ -11,7 +10,7 @@
% endif
</%def>
<%def name="render_buefy_form()">
<%def name="render_form()">
<p class="block">
Please select the "state" of the product, and enter the
@ -31,22 +30,22 @@
if you need to "receive" instead of "convert" the product.
</p>
${parent.render_buefy_form()}
${parent.render_form()}
</%def>
<%def name="buefy_form_body()">
<%def name="form_body()">
${render_buefy_field(dform['credit_type'])}
${form.render_field_complete('credit_type')}
${render_buefy_field(dform['quantity'])}
${form.render_field_complete('quantity')}
${render_buefy_field(dform['expiration_date'], bfield_kwargs={'v-show': "field_model_credit_type == 'expired'"})}
${form.render_field_complete('expiration_date', bfield_attrs={'v-show': "field_model_credit_type == 'expired'"})}
</%def>
<%def name="render_form()">
${form.render_deform(buttons=capture(self.render_form_buttons), form_body=capture(self.buefy_form_body))|n}
<%def name="render_form_template()">
${form.render_deform(buttons=capture(self.render_form_buttons), form_body=capture(self.form_body))|n}
</%def>

View file

@ -1,6 +1,5 @@
## -*- coding: utf-8; -*-
<%inherit file="/form.mako" />
<%namespace file="/forms/util.mako" import="render_buefy_field" />
<%def name="title()">Receive for Row #${row.sequence}</%def>
@ -11,7 +10,7 @@
% endif
</%def>
<%def name="render_buefy_form()">
<%def name="render_form()">
<p class="block">
Please select the "state" of the product, and enter the appropriate
@ -28,22 +27,22 @@
if you need to "convert" some already-received amount, into a credit.
</p>
${parent.render_buefy_form()}
${parent.render_form()}
</%def>
<%def name="buefy_form_body()">
<%def name="form_body()">
${render_buefy_field(dform['mode'])}
${form.render_field_complete('mode')}
${render_buefy_field(dform['quantity'])}
${form.render_field_complete('quantity')}
${render_buefy_field(dform['expiration_date'], bfield_kwargs={'v-show': "field_model_mode == 'expired'"})}
${form.render_field_complete('expiration_date', bfield_attrs={'v-show': "field_model_mode == 'expired'"})}
</%def>
<%def name="render_form()">
${form.render_deform(buttons=capture(self.render_form_buttons), form_body=capture(self.buefy_form_body))|n}
<%def name="render_form_template()">
${form.render_deform(buttons=capture(self.render_form_buttons), form_body=capture(self.form_body))|n}
</%def>

View file

@ -23,7 +23,7 @@
</style>
</%def>
<%def name="render_buefy_form()">
<%def name="render_form()">
<div class="form">
<p>Please select the type of report you wish to generate.</p>
<br />

View file

@ -5,7 +5,7 @@
<%def name="content_title()">New Report:&nbsp; ${report.name}</%def>
<%def name="render_buefy_form()">
<%def name="render_form()">
<div class="form">
<p class="block">
${report.__doc__}

View file

@ -1,8 +1,8 @@
## -*- coding: utf-8; -*-
<%inherit file="/master/view.mako" />
<%def name="render_buefy_form()">
${parent.render_buefy_form()}
<%def name="render_form()">
${parent.render_form()}
<email-preview-tools></email-preview-tools>
</%def>

View file

@ -75,7 +75,7 @@
% endif
</%def>
<%def name="render_buefy_form()">
<%def name="render_form()">
<div class="form">
<${form.component}
% if master.has_perm('execute'):

View file

@ -30,7 +30,7 @@
<b-select name="tailbone.${user.uuid}.buefy_css"
v-model="simpleSettings['tailbone.${user.uuid}.buefy_css']"
@input="settingsNeedSaved = true">
<option v-for="option in buefyCSSOptions"
<option v-for="option in themeStyleOptions"
:key="option.value"
:value="option.value">
{{ option.label }}
@ -46,7 +46,7 @@
${parent.modify_this_page_vars()}
<script type="text/javascript">
ThisPageData.buefyCSSOptions = ${json.dumps(buefy_css_options)|n}
ThisPageData.themeStyleOptions = ${json.dumps(theme_style_options)|n}
</script>
</%def>

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2023 Lance Edgar
# Copyright © 2010-2024 Lance Edgar
#
# This file is part of Rattail.
#
@ -32,23 +32,18 @@ import logging
import socket
import subprocess
import tempfile
import warnings
import json
import markdown
import sqlalchemy as sa
from sqlalchemy import orm
from rattail.db import model, Session as RattailSession
from rattail.db.util import short_session
from rattail.threads import Thread
from rattail.util import prettify, simple_error
from rattail.progress import SocketProgress
from rattail.util import simple_error
import colander
import deform
from deform import widget as dfwidget
from pyramid.renderers import render_to_response
from pyramid.response import FileResponse
from webhelpers2.html import HTML, tags
from tailbone import forms, grids
@ -115,7 +110,7 @@ class BatchMasterView(MasterView):
}
def __init__(self, request):
super(BatchMasterView, self).__init__(request)
super().__init__(request)
self.batch_handler = self.get_handler()
# TODO: deprecate / remove this (?)
self.handler = self.batch_handler
@ -167,7 +162,7 @@ class BatchMasterView(MasterView):
return self.rattail_config.batch_filepath(batch.batch_key, batch.uuid, filename)
def template_kwargs_view(self, **kwargs):
kwargs = super(BatchMasterView, self).template_kwargs_view(**kwargs)
kwargs = super().template_kwargs_view(**kwargs)
batch = kwargs['instance']
kwargs['batch'] = batch
kwargs['handler'] = self.handler
@ -195,8 +190,8 @@ class BatchMasterView(MasterView):
g.set_click_handler('title', "autoFilterStatus(props.row)")
kwargs['status_breakdown_data'] = breakdown
kwargs['status_breakdown_grid'] = HTML.literal(
g.render_buefy_table_element(data_prop='statusBreakdownData',
empty_labels=True))
g.render_table_element(data_prop='statusBreakdownData',
empty_labels=True))
return kwargs
@ -288,7 +283,8 @@ class BatchMasterView(MasterView):
return not batch.executed and not batch.complete
def configure_grid(self, g):
super(BatchMasterView, self).configure_grid(g)
super().configure_grid(g)
model = self.model
# created_by
CreatedBy = orm.aliased(model.User)
@ -337,7 +333,7 @@ class BatchMasterView(MasterView):
return batch.id_str
def configure_form(self, f):
super(BatchMasterView, self).configure_form(f)
super().configure_form(f)
# id
f.set_readonly('id')
@ -436,9 +432,9 @@ class BatchMasterView(MasterView):
label = HTML.literal(
'{{{{ togglingBatchComplete ? "Working, please wait..." : "{}" }}}}'.format(label))
submit = self.make_buefy_button(label, is_primary=True,
native_type='submit',
**{':disabled': 'togglingBatchComplete'})
submit = self.make_button(label, is_primary=True,
native_type='submit',
**{':disabled': 'togglingBatchComplete'})
form = [
begin_form,
@ -603,7 +599,7 @@ class BatchMasterView(MasterView):
return True
def configure_row_grid(self, g):
super(BatchMasterView, self).configure_row_grid(g)
super().configure_row_grid(g)
g.set_sort_defaults('sequence')
g.set_link('sequence')
@ -644,7 +640,7 @@ class BatchMasterView(MasterView):
if batch.executed:
self.request.session.flash("You cannot add new rows to a batch which has been executed")
return self.redirect(self.get_action_url('view', batch))
return super(BatchMasterView, self).create_row()
return super().create_row()
def save_create_row_form(self, form):
batch = self.get_instance()
@ -657,7 +653,7 @@ class BatchMasterView(MasterView):
self.handler.refresh_row(row)
def configure_row_form(self, f):
super(BatchMasterView, self).configure_row_form(f)
super().configure_row_form(f)
# sequence
f.set_readonly('sequence')
@ -681,9 +677,9 @@ class BatchMasterView(MasterView):
permission_prefix = self.get_permission_prefix()
if self.request.has_perm('{}.create_row'.format(permission_prefix)):
url = self.get_action_url('create_row', batch)
return self.make_buefy_button("New Row", url=url,
is_primary=True,
icon_left='plus')
return self.make_button("New Row", url=url,
is_primary=True,
icon_left='plus')
def make_batch_row_grid_tools(self, batch):
pass
@ -719,7 +715,7 @@ class BatchMasterView(MasterView):
kwargs['main_actions'] = actions
return super(BatchMasterView, self).make_row_grid_kwargs(**kwargs)
return super().make_row_grid_kwargs(**kwargs)
def make_row_grid_tools(self, batch):
return (self.make_default_row_grid_tools(batch) or '') + (self.make_batch_row_grid_tools(batch) or '')
@ -852,8 +848,11 @@ class BatchMasterView(MasterView):
labels = kwargs.setdefault('labels', {})
labels[field.name] = field.title
# auto-convert select widgets for buefy theme
# auto-convert select widgets for theme
if isinstance(field.widget, forms.widgets.PlainSelectWidget):
warnings.warn("PlainSelectWidget is deprecated; "
"please use deform.widget.SelectWidget instead",
DeprecationWarning)
field.widget = dfwidget.SelectWidget(values=field.widget.values)
if not schema:
@ -1022,7 +1021,8 @@ class BatchMasterView(MasterView):
cxn.close()
def catchup_versions(self, port, batch_uuid, username, *models):
with short_session() as s:
app = self.get_rattail_app()
with app.short_session() as s:
batch = s.get(self.model_class, batch_uuid)
batch_id = batch.id_str
description = str(batch)
@ -1048,8 +1048,10 @@ class BatchMasterView(MasterView):
"""
Thread target for populating batch data with progress indicator.
"""
app = self.get_rattail_app()
model = self.model
# mustn't use tailbone web session here
session = RattailSession()
session = app.make_session()
batch = session.get(self.model_class, batch_uuid)
user = session.get(model.User, user_uuid)
try:
@ -1107,7 +1109,9 @@ class BatchMasterView(MasterView):
# Refresh data for the batch, with progress. Note that we must use the
# rattail session here; can't use tailbone because it has web request
# transaction binding etc.
session = RattailSession()
app = self.get_rattail_app()
model = self.model
session = app.make_session()
batch = session.get(self.model_class, batch_uuid)
cognizer = session.get(model.User, user_uuid) if user_uuid else None
try:
@ -1160,7 +1164,9 @@ class BatchMasterView(MasterView):
"""
Thread target for refreshing multiple batches with progress indicator.
"""
session = RattailSession()
app = self.get_rattail_app()
model = self.model
session = app.make_session()
batches = batches.with_session(session).all()
user = session.get(model.User, user_uuid)
try:
@ -1257,7 +1263,7 @@ class BatchMasterView(MasterView):
self.handler.do_remove_row(row)
def delete_row_objects(self, rows):
deleted = super(BatchMasterView, self).delete_row_objects(rows)
deleted = super().delete_row_objects(rows)
batch = self.get_instance()
# decrement rowcount for batch
@ -1300,7 +1306,9 @@ class BatchMasterView(MasterView):
# Execute the batch, with progress. Note that we must use the rattail
# session here; can't use tailbone because it has web request
# transaction binding etc.
session = RattailSession()
app = self.get_rattail_app()
model = self.model
session = app.make_session()
batch = self.get_instance_for_key(key, session)
user = session.get(model.User, user_uuid)
try:
@ -1375,7 +1383,9 @@ class BatchMasterView(MasterView):
"""
Thread target for executing multiple batches with progress indicator.
"""
session = RattailSession()
app = self.get_rattail_app()
model = self.model
session = app.make_session()
batches = batches.with_session(session).all()
user = session.get(model.User, user_uuid)
try:
@ -1415,7 +1425,7 @@ class BatchMasterView(MasterView):
return self.get_index_url()
def get_row_csv_fields(self):
fields = super(BatchMasterView, self).get_row_csv_fields()
fields = super().get_row_csv_fields()
fields = [field for field in fields
if field not in ('uuid', 'batch_uuid', 'removed')]
return fields
@ -1538,7 +1548,7 @@ class FileBatchMasterView(BatchMasterView):
return uploads
def configure_form(self, f):
super(FileBatchMasterView, self).configure_form(f)
super().configure_form(f)
batch = f.model_instance
# filename

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2023 Lance Edgar
# Copyright © 2010-2024 Lance Edgar
#
# This file is part of Rattail.
#
@ -26,12 +26,12 @@ Views for handheld batches
from collections import OrderedDict
from rattail.db import model
from rattail.db.model import HandheldBatch, HandheldBatchRow
import colander
from deform import widget as dfwidget
from webhelpers2.html import tags
from tailbone import forms
from tailbone.views.batch import FileBatchMasterView
@ -46,14 +46,14 @@ class ExecutionOptions(colander.Schema):
action = colander.SchemaNode(
colander.String(),
validator=colander.OneOf(ACTION_OPTIONS),
widget=forms.widgets.PlainSelectWidget(values=ACTION_OPTIONS.items()))
widget=dfwidget.SelectWidget(values=ACTION_OPTIONS.items()))
class HandheldBatchView(FileBatchMasterView):
"""
Master view for handheld batches.
"""
model_class = model.HandheldBatch
model_class = HandheldBatch
default_handler_spec = 'rattail.batch.handheld:HandheldBatchHandler'
model_title_plural = "Handheld Batches"
route_prefix = 'batch.handheld'
@ -61,7 +61,7 @@ class HandheldBatchView(FileBatchMasterView):
execution_options_schema = ExecutionOptions
editable = False
model_row_class = model.HandheldBatchRow
model_row_class = HandheldBatchRow
rows_creatable = False
rows_editable = True
@ -116,7 +116,7 @@ class HandheldBatchView(FileBatchMasterView):
]
def configure_grid(self, g):
super(HandheldBatchView, self).configure_grid(g)
super().configure_grid(g)
device_types = OrderedDict(sorted(self.enum.HANDHELD_DEVICE_TYPE.items(),
key=lambda item: item[1]))
g.set_enum('device_type', device_types)
@ -126,7 +126,7 @@ class HandheldBatchView(FileBatchMasterView):
return 'notice'
def configure_form(self, f):
super(HandheldBatchView, self).configure_form(f)
super().configure_form(f)
batch = f.model_instance
# device_type
@ -156,13 +156,13 @@ class HandheldBatchView(FileBatchMasterView):
return tags.link_to(text, url)
def get_batch_kwargs(self, batch):
kwargs = super(HandheldBatchView, self).get_batch_kwargs(batch)
kwargs = super().get_batch_kwargs(batch)
kwargs['device_type'] = batch.device_type
kwargs['device_name'] = batch.device_name
return kwargs
def configure_row_grid(self, g):
super(HandheldBatchView, self).configure_row_grid(g)
super().configure_row_grid(g)
g.set_type('cases', 'quantity')
g.set_type('units', 'quantity')
g.set_label('brand_name', "Brand")
@ -172,7 +172,7 @@ class HandheldBatchView(FileBatchMasterView):
return 'warning'
def configure_row_form(self, f):
super(HandheldBatchView, self).configure_row_form(f)
super().configure_row_form(f)
# readonly fields
f.set_readonly('upc')
@ -188,7 +188,7 @@ class HandheldBatchView(FileBatchMasterView):
return self.request.route_url('batch.inventory.view', uuid=result.uuid)
elif kwargs['action'] == 'make_label_batch':
return self.request.route_url('labels.batch.view', uuid=result.uuid)
return super(HandheldBatchView, self).get_execute_success_url(batch)
return super().get_execute_success_url(batch)
def get_execute_results_success_url(self, result, **kwargs):
if result is True:

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2023 Lance Edgar
# Copyright © 2010-2024 Lance Edgar
#
# This file is part of Rattail.
#
@ -206,7 +206,7 @@ class POSBatchView(BatchMasterView):
)
return HTML.literal(
g.render_buefy_table_element(data_prop='taxesData'))
g.render_table_element(data_prop='taxesData'))
def template_kwargs_view(self, **kwargs):
kwargs = super().template_kwargs_view(**kwargs)

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2023 Lance Edgar
# Copyright © 2010-2024 Lance Edgar
#
# This file is part of Rattail.
#
@ -26,12 +26,12 @@ Views for generic product batches
from collections import OrderedDict
from rattail.db import model
from rattail.db.model import ProductBatch, ProductBatchRow
import colander
from deform import widget as dfwidget
from webhelpers2.html import HTML
from tailbone import forms
from tailbone.views.batch import BatchMasterView
@ -46,15 +46,15 @@ class ExecutionOptions(colander.Schema):
action = colander.SchemaNode(
colander.String(),
validator=colander.OneOf(ACTION_OPTIONS),
widget=forms.widgets.PlainSelectWidget(values=ACTION_OPTIONS.items()))
widget=dfwidget.SelectWidget(values=ACTION_OPTIONS.items()))
class ProductBatchView(BatchMasterView):
"""
Master view for product batches.
"""
model_class = model.ProductBatch
model_row_class = model.ProductBatchRow
model_class = ProductBatch
model_row_class = ProductBatchRow
default_handler_spec = 'rattail.batch.product:ProductBatchHandler'
route_prefix = 'batch.product'
url_prefix = '/batches/product'
@ -129,7 +129,7 @@ class ProductBatchView(BatchMasterView):
]
def configure_form(self, f):
super(ProductBatchView, self).configure_form(f)
super().configure_form(f)
# input_filename
if self.creating:
@ -139,7 +139,8 @@ class ProductBatchView(BatchMasterView):
f.set_renderer('input_filename', self.render_downloadable_file)
def configure_row_grid(self, g):
super(ProductBatchView, self).configure_row_grid(g)
super().configure_row_grid(g)
model = self.model
g.set_joiner('vendor', lambda q: q.outerjoin(model.Vendor))
g.set_sorter('vendor', model.Vendor.name)
@ -165,7 +166,7 @@ class ProductBatchView(BatchMasterView):
return 'warning'
def configure_row_form(self, f):
super(ProductBatchView, self).configure_row_form(f)
super().configure_row_form(f)
f.set_type('upc', 'gpc')
@ -204,10 +205,10 @@ class ProductBatchView(BatchMasterView):
return self.request.route_url('labels.batch.view', uuid=result.uuid)
elif kwargs['action'] == 'make_pricing_batch':
return self.request.route_url('batch.pricing.view', uuid=result.uuid)
return super(ProductBatchView, self).get_execute_success_url(batch)
return super().get_execute_success_url(batch)
def get_row_csv_fields(self):
fields = super(ProductBatchView, self).get_row_csv_fields()
fields = super().get_row_csv_fields()
if 'vendor_uuid' in fields:
i = fields.index('vendor_uuid')
@ -273,12 +274,12 @@ class ProductBatchView(BatchMasterView):
data['report_name'] = (report.name or '') if report else ''
def get_row_csv_row(self, row, fields):
csvrow = super(ProductBatchView, self).get_row_csv_row(row, fields)
csvrow = super().get_row_csv_row(row, fields)
self.supplement_row_data(row, fields, csvrow)
return csvrow
def get_row_xlsx_row(self, row, fields):
xlrow = super(ProductBatchView, self).get_row_xlsx_row(row, fields)
xlrow = super().get_row_xlsx_row(row, fields)
self.supplement_row_data(row, fields, xlrow)
return xlrow

View file

@ -341,7 +341,7 @@ class CustomerView(MasterView):
# people
if self.should_expose_people():
if self.viewing:
f.set_renderer('people', self.render_people_buefy)
f.set_renderer('people', self.render_people)
else:
f.remove('people')
else:
@ -463,20 +463,6 @@ class CustomerView(MasterView):
url = self.request.route_url('people.view', uuid=person.uuid)
return tags.link_to(text, url)
# TODO: remove if no longer used
def render_people(self, customer, field):
people = customer.people
if not people:
return ""
items = []
for person in people:
text = str(person)
url = self.request.route_url('people.view', uuid=person.uuid)
link = tags.link_to(text, url)
items.append(HTML.tag('li', c=[link]))
return HTML.tag('ul', c=items)
def render_shoppers(self, customer, field):
route_prefix = self.get_route_prefix()
permission_prefix = self.get_permission_prefix()
@ -504,9 +490,9 @@ class CustomerView(MasterView):
)
return HTML.literal(
g.render_buefy_table_element(data_prop='shoppers'))
g.render_table_element(data_prop='shoppers'))
def render_people_buefy(self, customer, field):
def render_people(self, customer, field):
route_prefix = self.get_route_prefix()
permission_prefix = self.get_permission_prefix()
@ -533,7 +519,7 @@ class CustomerView(MasterView):
click_handler="$emit('detach-person', props.row._action_url_detach)"))
return HTML.literal(
g.render_buefy_table_element(data_prop='peopleData'))
g.render_table_element(data_prop='peopleData'))
def render_groups(self, customer, field):
groups = customer.groups

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2023 Lance Edgar
# Copyright © 2010-2024 Lance Edgar
#
# This file is part of Rattail.
#
@ -401,7 +401,7 @@ class CustomerOrderItemView(MasterView):
)
table = HTML.literal(
g.render_buefy_table_element(data_prop='eventsData'))
g.render_table_element(data_prop='eventsData'))
elements = [table]
if self.has_perm('add_note'):

View file

@ -144,7 +144,7 @@ class DepartmentView(MasterView):
g.main_actions.append(self.make_action('edit', icon='edit'))
return HTML.literal(
g.render_buefy_table_element(data_prop='employeesData'))
g.render_table_element(data_prop='employeesData'))
def template_kwargs_view(self, **kwargs):
kwargs = super().template_kwargs_view(**kwargs)

View file

@ -30,7 +30,6 @@ import csv
import datetime
import getpass
import shutil
import tempfile
import logging
from collections import OrderedDict
@ -40,12 +39,10 @@ from sqlalchemy import orm
import sqlalchemy_continuum as continuum
from sqlalchemy_utils.functions import get_primary_keys, get_columns
from rattail.db import model, Session as RattailSession
from rattail.db.continuum import model_transaction_query
from rattail.util import simple_error, get_class_hierarchy
from rattail.threads import Thread
from rattail.csvutil import UnicodeDictWriter
from rattail.files import temp_path
from rattail.excel import ExcelWriter
from rattail.gpc import GPC
@ -54,7 +51,6 @@ import deform
from deform import widget as dfwidget
from pyramid import httpexceptions
from pyramid.renderers import get_renderer, render_to_response, render
from pyramid.response import FileResponse
from webhelpers2.html import HTML, tags
from webob.compat import cgi_FieldStorage
@ -220,7 +216,8 @@ class MasterView(View):
to the current thread (one per request), this method should instead
return e.g. a new independent ``rattail.db.Session`` instance.
"""
return RattailSession()
app = self.get_rattail_app()
return app.make_session()
@classmethod
def get_grid_factory(cls):
@ -348,7 +345,7 @@ class MasterView(View):
# return grid data only, if partial page was requested
if self.request.params.get('partial'):
return self.json_response(grid.get_buefy_data())
return self.json_response(grid.get_table_data())
context = {
'grid': grid,
@ -719,10 +716,11 @@ class MasterView(View):
return obj
def normalize_uploads(self, form, skip=None):
app = self.get_rattail_app()
uploads = {}
def normalize(filedict):
tempdir = tempfile.mkdtemp()
tempdir = app.make_temp_dir()
filepath = os.path.join(tempdir, filedict['filename'])
tmpinfo = form.deform_form[node.name].widget.tmpstore.get(filedict['uid'])
tmpdata = tmpinfo['fp'].read()
@ -1114,7 +1112,8 @@ class MasterView(View):
Thread target for populating new object with progress indicator.
"""
# mustn't use tailbone web session here
session = RattailSession()
app = self.get_rattail_app()
session = app.make_session()
obj = session.get(self.model_class, uuid)
try:
self.populate_object(session, obj, progress=progress)
@ -1175,7 +1174,7 @@ class MasterView(View):
# return grid only, if partial page was requested
if self.request.params.get('partial'):
# render grid data only, as JSON
return self.json_response(grid.get_buefy_data())
return self.json_response(grid.get_table_data())
context = {
'instance': instance,
@ -1308,7 +1307,7 @@ class MasterView(View):
# return grid only, if partial page was requested
if self.request.params.get('partial'):
# render grid data only, as JSON
return self.json_response(grid.get_buefy_data())
return self.json_response(grid.get_table_data())
return self.render_to_response('versions', {
'instance': instance,
@ -1360,6 +1359,7 @@ class MasterView(View):
return classes
def make_revisions_grid(self, obj, empty_data=False):
model = self.model
route_prefix = self.get_route_prefix()
row_url = lambda txn, i: self.request.route_url(f'{route_prefix}.version',
uuid=obj.uuid,
@ -1396,8 +1396,8 @@ class MasterView(View):
grid = self.make_version_grid(**kwargs)
grid.set_joiner('user', lambda q: q.outerjoin(self.model.User))
grid.set_sorter('user', self.model.User.username)
grid.set_joiner('user', lambda q: q.outerjoin(model.User))
grid.set_sorter('user', model.User.username)
grid.set_link('remote_addr')
@ -1465,7 +1465,7 @@ class MasterView(View):
else: # no txnid, return grid data
obj = self.get_instance()
grid = self.make_revisions_grid(obj)
return grid.get_buefy_data()
return grid.get_table_data()
def view_version(self):
"""
@ -1770,16 +1770,10 @@ class MasterView(View):
path = self.download_path(obj, filename)
if not path or not os.path.exists(path):
raise self.notfound()
response = FileResponse(path, request=self.request)
response.content_length = os.path.getsize(path)
response = self.file_response(path)
content_type = self.download_content_type(path, filename)
if content_type:
response.content_type = content_type
# content-disposition
filename = os.path.basename(path)
response.content_disposition = str('attachment; filename="{}"'.format(filename))
return response
def download_content_type(self, path, filename):
@ -1856,7 +1850,7 @@ class MasterView(View):
View for deleting an existing model record.
"""
if not self.deletable:
raise httpexceptions.HTTPForbidden()
raise self.forbidden()
self.deleting = True
instance = self.get_instance()
@ -2111,7 +2105,9 @@ class MasterView(View):
"""
Thread target for executing an object.
"""
session = RattailSession()
app = self.get_rattail_app()
model = self.model
session = app.make_session()
obj = self.get_instance_for_key(key, session)
user = session.get(model.User, user_uuid)
try:
@ -2926,11 +2922,11 @@ class MasterView(View):
normal.append(button)
return normal
def make_buefy_button(self, label,
type=None, is_primary=False,
url=None, target=None, is_external=False,
icon_left=None,
**kwargs):
def make_button(self, label,
type=None, is_primary=False,
url=None, target=None, is_external=False,
icon_left=None,
**kwargs):
"""
Make and return a HTML ``<b-button>`` literal.
"""
@ -2983,7 +2979,7 @@ class MasterView(View):
assumed to be external, which affects the icon and causes
button click to open link in a new tab.
"""
# TODO: this should call make_buefy_button()
# TODO: this should call make_button()
# nb. unfortunately HTML.tag() calls its first arg 'tag' and
# so we can't pass a kwarg with that name...so instead we
@ -4067,10 +4063,11 @@ class MasterView(View):
"""
Download current *row* results as XLSX.
"""
app = self.get_rattail_app()
obj = self.get_instance()
results = self.get_effective_row_data(sort=True)
fields = self.get_row_xlsx_fields()
path = temp_path(suffix='.xlsx')
path = app.make_temp_file(suffix='.xlsx')
writer = ExcelWriter(path, fields, sheet_title=self.get_row_model_title_plural())
writer.write_header()
@ -5039,6 +5036,7 @@ class MasterView(View):
"""
Generic view for configuring some aspect of the software.
"""
app = self.get_rattail_app()
if self.request.method == 'POST':
if self.request.POST.get('remove_settings'):
self.configure_remove_settings()
@ -5053,7 +5051,7 @@ class MasterView(View):
uploads = {}
for key, value in data.items():
if isinstance(value, cgi_FieldStorage):
tempdir = tempfile.mkdtemp()
tempdir = app.make_temp_dir()
filename = os.path.basename(value.filename)
filepath = os.path.join(tempdir, filename)
with open(filepath, 'wb') as f:

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2023 Lance Edgar
# Copyright © 2010-2024 Lance Edgar
#
# This file is part of Rattail.
#
@ -29,10 +29,8 @@ from rattail.time import localtime
import colander
from deform import widget as dfwidget
from pyramid import httpexceptions
from webhelpers2.html import tags, HTML
# from tailbone import forms
from tailbone.db import Session
from tailbone.views import MasterView
from tailbone.util import raw_datetime
@ -83,15 +81,15 @@ class MessageView(MasterView):
def index(self):
if not self.request.user:
raise httpexceptions.HTTPForbidden
raise self.forbidden()
return super().index()
def get_instance(self):
if not self.request.user:
raise httpexceptions.HTTPForbidden
raise self.forbidden()
message = super().get_instance()
if not self.associated_with(message):
raise httpexceptions.HTTPForbidden
raise self.forbidden()
return message
def associated_with(self, message):
@ -395,7 +393,7 @@ class MessageView(MasterView):
message = self.get_instance()
recipient = self.get_recipient(message)
if not recipient:
raise httpexceptions.HTTPForbidden
raise self.forbidden()
dest = self.request.GET.get('dest')
if dest not in ('inbox', 'archive'):
@ -520,7 +518,7 @@ class RecipientsWidgetBuefy(dfwidget.Widget):
"""
Custom "message recipients" widget, for use with Buefy / Vue.js themes.
"""
template = 'message_recipients_buefy'
template = 'message_recipients'
def deserialize(self, field, pstruct):
if pstruct is colander.null:

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2023 Lance Edgar
# Copyright © 2010-2024 Lance Edgar
#
# This file is part of Rattail.
#
@ -43,7 +43,7 @@ class PrincipalMasterView(MasterView):
def get_fallback_templates(self, template, **kwargs):
return [
'/principal/{}.mako'.format(template),
] + super(PrincipalMasterView, self).get_fallback_templates(template, **kwargs)
] + super().get_fallback_templates(template, **kwargs)
def perm_sortkey(self, item):
key, value = item
@ -74,9 +74,9 @@ class PrincipalMasterView(MasterView):
context = {'permissions': sorted_perms, 'principals': principals}
perms = self.get_buefy_perms_data(sorted_perms)
context['buefy_perms'] = perms
context['buefy_sorted_groups'] = list(perms)
perms = self.get_perms_data(sorted_perms)
context['perms_data'] = perms
context['sorted_groups_data'] = list(perms)
if permission_group and permission_group not in perms:
permission_group = None
@ -95,7 +95,7 @@ class PrincipalMasterView(MasterView):
return self.render_to_response('find_by_perm', context)
def get_buefy_perms_data(self, sorted_perms):
def get_perms_data(self, sorted_perms):
data = OrderedDict()
for gkey, group in sorted_perms:

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2023 Lance Edgar
# Copyright © 2010-2024 Lance Edgar
#
# This file is part of Rattail.
#
@ -37,8 +37,7 @@ from rattail.db import model, api, auth, Session as RattailSession
from rattail.gpc import GPC
from rattail.threads import Thread
from rattail.exceptions import LabelPrintingError
from rattail.util import load_object, pretty_quantity, simple_error
from rattail.time import localtime, make_utc
from rattail.util import simple_error
import colander
from deform import widget as dfwidget
@ -417,13 +416,13 @@ class ProductView(MasterView):
app = self.get_rattail_app()
if price.starts:
starts = localtime(self.rattail_config, price.starts, from_utc=True)
starts = app.localtime(price.starts, from_utc=True)
starts = app.render_date(starts.date())
else:
starts = "??"
if price.ends:
ends = localtime(self.rattail_config, price.ends, from_utc=True)
ends = app.localtime(price.ends, from_utc=True)
ends = app.render_date(ends.date())
else:
ends = "??"
@ -456,23 +455,25 @@ class ProductView(MasterView):
default=True)
def render_regular_price(self, product, field):
app = self.get_rattail_app()
text = self.render_price(product, field)
if text and self.show_price_effective_dates():
history = self.get_regular_price_history(product)
if history:
date = localtime(self.rattail_config, history[0]['changed'], from_utc=True).date()
date = app.localtime(history[0]['changed'], from_utc=True).date()
text = "{} (as of {})".format(text, date)
return self.add_price_history_link(text, 'regular')
def render_current_price(self, product, field):
app = self.get_rattail_app()
text = self.render_price(product, field)
if text and self.show_price_effective_dates():
history = self.get_current_price_history(product)
if history:
date = localtime(self.rattail_config, history[0]['changed'], from_utc=True).date()
date = app.localtime(history[0]['changed'], from_utc=True).date()
text = "{} (as of {})".format(text, date)
return self.add_price_history_link(text, 'current')
@ -489,10 +490,11 @@ class ProductView(MasterView):
if not text:
return
app = self.get_rattail_app()
if self.show_price_effective_dates():
history = self.get_suggested_price_history(product)
if history:
date = localtime(self.rattail_config, history[0]['changed'], from_utc=True).date()
date = app.localtime(history[0]['changed'], from_utc=True).date()
text = "{} (as of {})".format(text, date)
text = self.warn_if_regprice_more_than_srp(product, text)
@ -526,13 +528,15 @@ class ProductView(MasterView):
inventory = product.inventory
if not inventory:
return ""
return pretty_quantity(inventory.on_hand)
app = self.get_rattail_app()
return app.render_quantity(inventory.on_hand)
def render_on_order(self, product, column):
inventory = product.inventory
if not inventory:
return ""
return pretty_quantity(inventory.on_order)
app = self.get_rattail_app()
return app.render_quantity(inventory.on_order)
def template_kwargs_index(self, **kwargs):
kwargs = super().template_kwargs_index(**kwargs)
@ -1105,7 +1109,8 @@ class ProductView(MasterView):
value = product.inventory.on_hand
if not value:
return ""
return pretty_quantity(value)
app = self.get_rattail_app()
return app.render_quantity(value)
def render_inventory_on_order(self, product, field):
if not product.inventory:
@ -1113,7 +1118,8 @@ class ProductView(MasterView):
value = product.inventory.on_order
if not value:
return ""
return pretty_quantity(value)
app = self.get_rattail_app()
return app.render_quantity(value)
def price_history(self):
"""
@ -1136,7 +1142,7 @@ class ProductView(MasterView):
if price is not None:
history['price'] = float(price)
history['price_display'] = app.render_currency(price)
changed = localtime(self.rattail_config, history['changed'], from_utc=True)
changed = app.localtime(history['changed'], from_utc=True)
history['changed'] = str(changed)
history['changed_display_html'] = raw_datetime(self.rattail_config, changed)
user = history.pop('changed_by')
@ -1149,6 +1155,7 @@ class ProductView(MasterView):
"""
AJAX view for fetching cost history for a product.
"""
app = self.get_rattail_app()
product = self.get_instance()
data = self.get_cost_history(product)
@ -1162,7 +1169,7 @@ class ProductView(MasterView):
history['cost_display'] = "${:0.2f}".format(cost)
else:
history['cost_display'] = None
changed = localtime(self.rattail_config, history['changed'], from_utc=True)
changed = app.localtime(history['changed'], from_utc=True)
history['changed'] = str(changed)
history['changed_display_html'] = raw_datetime(self.rattail_config, changed)
user = history.pop('changed_by')
@ -1388,10 +1395,11 @@ class ProductView(MasterView):
Returns a sequence of "records" which corresponds to the given
product's regular price history.
"""
app = self.get_rattail_app()
Transaction = continuum.transaction_class(model.Product)
ProductVersion = continuum.version_class(model.Product)
ProductPriceVersion = continuum.version_class(model.ProductPrice)
now = make_utc()
now = app.make_utc()
history = []
# first we find all relevant ProductVersion records
@ -1457,10 +1465,11 @@ class ProductView(MasterView):
Returns a sequence of "records" which corresponds to the given
product's current price history.
"""
app = self.get_rattail_app()
Transaction = continuum.transaction_class(model.Product)
ProductVersion = continuum.version_class(model.Product)
ProductPriceVersion = continuum.version_class(model.ProductPrice)
now = make_utc()
now = app.make_utc()
history = []
# first we find all relevant ProductVersion records
@ -1599,10 +1608,11 @@ class ProductView(MasterView):
Returns a sequence of "records" which corresponds to the given
product's SRP history.
"""
app = self.get_rattail_app()
Transaction = continuum.transaction_class(model.Product)
ProductVersion = continuum.version_class(model.Product)
ProductPriceVersion = continuum.version_class(model.ProductPrice)
now = make_utc()
now = app.make_utc()
history = []
# first we find all relevant ProductVersion records
@ -1668,10 +1678,11 @@ class ProductView(MasterView):
Returns a sequence of "records" which corresponds to the given
product's cost history.
"""
app = self.get_rattail_app()
Transaction = continuum.transaction_class(model.Product)
ProductVersion = continuum.version_class(model.Product)
ProductCostVersion = continuum.version_class(model.ProductCost)
now = make_utc()
now = app.make_utc()
history = []
# we just find all relevant (preferred!) ProductCostVersion records
@ -1948,10 +1959,11 @@ class ProductView(MasterView):
"""
View for making a new batch from current product grid query.
"""
app = self.get_rattail_app()
supported = self.get_supported_batches()
batch_options = []
for key, info in list(supported.items()):
handler = load_object(info['spec'])(self.rattail_config)
handler = app.load_object(info['spec'])(self.rattail_config)
handler.spec = info['spec']
handler.option_key = key
handler.option_title = info.get('title', handler.get_model_title())
@ -2448,19 +2460,19 @@ class PendingProductView(MasterView):
if (self.has_perm('ignore_product')
and status in (self.enum.PENDING_PRODUCT_STATUS_PENDING,
self.enum.PENDING_PRODUCT_STATUS_READY)):
buttons.append(self.make_buefy_button("Ignore Product",
type='is-warning',
icon_left='ban',
**{'@click': "$emit('ignore-product')"}))
buttons.append(self.make_button("Ignore Product",
type='is-warning',
icon_left='ban',
**{'@click': "$emit('ignore-product')"}))
if (self.has_perm('resolve_product')
and status in (self.enum.PENDING_PRODUCT_STATUS_PENDING,
self.enum.PENDING_PRODUCT_STATUS_READY,
self.enum.PENDING_PRODUCT_STATUS_IGNORED)):
buttons.append(self.make_buefy_button("Resolve Product",
is_primary=True,
icon_left='object-ungroup',
**{'@click': "$emit('resolve-product')"}))
buttons.append(self.make_button("Resolve Product",
is_primary=True,
icon_left='object-ungroup',
**{'@click': "$emit('resolve-product')"}))
if buttons:
text = HTML.tag('span', class_='control', c=[text])

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2023 Lance Edgar
# Copyright © 2010-2024 Lance Edgar
#
# This file is part of Rattail.
#
@ -28,10 +28,9 @@ from rattail.db.model import PurchaseBatch, PurchaseBatchRow
import colander
from deform import widget as dfwidget
from pyramid import httpexceptions
from webhelpers2.html import tags, HTML
from tailbone import forms, grids
from tailbone import forms
from tailbone.views.batch import BatchMasterView
@ -826,7 +825,7 @@ class PurchasingBatchView(BatchMasterView):
def render_row_credits(self, row, field):
g = self.make_row_credits_grid(row)
return HTML.literal(
g.render_buefy_table_element(data_prop='rowData.credits'))
g.render_table_element(data_prop='rowData.credits'))
# def before_create_row(self, form):
# row = form.fieldset.model

View file

@ -310,8 +310,6 @@ class OrderingBatchView(PurchasingBatchView):
if not order_date:
order_date = localtime(self.rattail_config).date()
buefy_data = self.get_worksheet_buefy_data(departments)
return self.render_to_response('worksheet', {
'batch': batch,
'order_date': order_date,
@ -324,10 +322,10 @@ class OrderingBatchView(PurchasingBatchView):
'get_upc': lambda p: p.upc.pretty() if p.upc else '',
'header_columns': self.order_form_header_columns,
'ignore_cases': not self.handler.allow_cases(),
'worksheet_data': buefy_data,
'worksheet_data': self.get_worksheet_data(departments),
})
def get_worksheet_buefy_data(self, departments):
def get_worksheet_data(self, departments):
data = {}
for department in departments.values():
for subdepartment in department._order_subdepartments.values():

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2023 Lance Edgar
# Copyright © 2010-2024 Lance Edgar
#
# This file is part of Rattail.
#
@ -33,12 +33,10 @@ from collections import OrderedDict
import humanize
from rattail import pod
from rattail.time import localtime, make_utc
from rattail.util import pretty_quantity, prettify, simple_error
from rattail.util import prettify, simple_error
import colander
from deform import widget as dfwidget
from pyramid import httpexceptions
from webhelpers2.html import tags, HTML
from tailbone import forms, grids
@ -781,8 +779,8 @@ class ReceivingBatchView(PurchasingBatchView):
g.set_click_handler('title', "autoFilterPoVsInvoice(props.row)")
kwargs['po_vs_invoice_breakdown_data'] = breakdown
kwargs['po_vs_invoice_breakdown_grid'] = HTML.literal(
g.render_buefy_table_element(data_prop='poVsInvoiceBreakdownData',
empty_labels=True))
g.render_table_element(data_prop='poVsInvoiceBreakdownData',
empty_labels=True))
kwargs['allow_edit_catalog_unit_cost'] = self.allow_edit_catalog_unit_cost(batch)
kwargs['allow_edit_invoice_unit_cost'] = self.allow_edit_invoice_unit_cost(batch)
@ -1137,6 +1135,7 @@ class ReceivingBatchView(PurchasingBatchView):
"""
Primary desktop view for row-level receiving.
"""
app = self.get_rattail_app()
# TODO: this code was largely copied from mobile_receive_row() but it
# tries to pave the way for shared logic, i.e. where the latter would
# simply invoke this method and return the result. however we're not
@ -1270,7 +1269,7 @@ class ReceivingBatchView(PurchasingBatchView):
if accounted_for:
# some product accounted for; button should receive "remainder" only
if remainder:
remainder = pretty_quantity(remainder)
remainder = app.render_quantity(remainder)
context['quick_receive_quantity'] = remainder
context['quick_receive_text'] = "Receive Remainder ({} {})".format(remainder, context['unit_uom'])
else:
@ -1280,7 +1279,7 @@ class ReceivingBatchView(PurchasingBatchView):
else: # nothing yet accounted for, button should receive "all"
if not remainder:
raise ValueError("why is remainder empty?")
remainder = pretty_quantity(remainder)
remainder = app.render_quantity(remainder)
context['quick_receive_quantity'] = remainder
context['quick_receive_text'] = "Receive ALL ({} {})".format(remainder, context['unit_uom'])

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2023 Lance Edgar
# Copyright © 2010-2024 Lance Edgar
#
# This file is part of Rattail.
#
@ -32,9 +32,8 @@ import logging
from collections import OrderedDict
import rattail
from rattail.db import model, Session as RattailSession
from rattail.db.model import ReportOutput
from rattail.files import resource_path
from rattail.time import localtime
from rattail.threads import Thread
from rattail.util import simple_error
@ -81,6 +80,7 @@ class OrderingWorksheet(View):
upc_getter = staticmethod(get_upc)
def __call__(self):
model = self.model
if self.request.params.get('vendor'):
vendor = Session.get(model.Vendor, self.request.params['vendor'])
if vendor:
@ -104,7 +104,8 @@ class OrderingWorksheet(View):
"""
Rendering engine for the ordering worksheet report.
"""
app = self.get_rattail_app()
model = self.model
q = Session.query(model.ProductCost)
q = q.join(model.Product)
q = q.filter(model.Product.deleted == False)
@ -127,7 +128,7 @@ class OrderingWorksheet(View):
key = '{0} {1}'.format(brand, product.description)
return key
now = localtime(self.request.rattail_config)
now = app.localtime()
data = dict(
vendor=vendor,
costs=costs,
@ -157,7 +158,7 @@ class InventoryWorksheet(View):
"""
This is the "Inventory Worksheet" report.
"""
model = self.model
departments = Session.query(model.Department)
if self.request.params.get('department'):
@ -178,6 +179,8 @@ class InventoryWorksheet(View):
"""
Generates the Inventory Worksheet report.
"""
app = self.get_rattail_app()
model = self.model
def get_products(subdepartment):
q = Session.query(model.Product)
@ -191,7 +194,7 @@ class InventoryWorksheet(View):
q = q.order_by(model.Brand.name, model.Product.description)
return q.all()
now = localtime(self.request.rattail_config)
now = app.localtime()
data = dict(
date=now.strftime('%a %d %b %Y'),
time=now.strftime('%I:%M %p'),
@ -209,7 +212,7 @@ class ReportOutputView(ExportMasterView):
"""
Master view for report output
"""
model_class = model.ReportOutput
model_class = ReportOutput
route_prefix = 'report_output'
url_prefix = '/reports/generated'
creatable = True
@ -238,7 +241,7 @@ class ReportOutputView(ExportMasterView):
]
def __init__(self, request):
super(ReportOutputView, self).__init__(request)
super().__init__(request)
self.report_handler = self.get_report_handler()
def get_report_handler(self):
@ -246,7 +249,7 @@ class ReportOutputView(ExportMasterView):
return app.get_report_handler()
def configure_grid(self, g):
super(ReportOutputView, self).configure_grid(g)
super().configure_grid(g)
g.filters['report_name'].default_active = True
g.filters['report_name'].default_verb = 'contains'
@ -254,7 +257,7 @@ class ReportOutputView(ExportMasterView):
g.set_link('filename')
def configure_form(self, f):
super(ReportOutputView, self).configure_form(f)
super().configure_form(f)
# report_type
f.set_renderer('report_type', self.render_report_type)
@ -282,10 +285,10 @@ class ReportOutputView(ExportMasterView):
# add help button if report has a link
report = self.report_handler.get_report(type_key)
if report and report.help_url:
button = self.make_buefy_button("Help for this report",
url=report.help_url,
is_external=True,
icon_left='question-circle')
button = self.make_button("Help for this report",
url=report.help_url,
is_external=True,
icon_left='question-circle')
button = HTML.tag('div', class_='level-item', c=[button])
rendered = HTML.tag('div', class_='level-item', c=[rendered])
rendered = HTML.tag('div', class_='level-left', c=[rendered, button])
@ -311,7 +314,7 @@ class ReportOutputView(ExportMasterView):
labels={'key': "Name"},
)
return HTML.literal(
g.render_buefy_table_element(data_prop='paramsData'))
g.render_table_element(data_prop='paramsData'))
def get_params_context(self, report):
params_data = []
@ -323,7 +326,7 @@ class ReportOutputView(ExportMasterView):
return params_data
def template_kwargs_view(self, **kwargs):
kwargs = super(ReportOutputView, self).template_kwargs_view(**kwargs)
kwargs = super().template_kwargs_view(**kwargs)
output = kwargs['instance']
kwargs['params_data'] = self.get_params_context(output)
@ -339,7 +342,7 @@ class ReportOutputView(ExportMasterView):
return kwargs
def template_kwargs_delete(self, **kwargs):
kwargs = super(ReportOutputView, self).template_kwargs_delete(**kwargs)
kwargs = super().template_kwargs_delete(**kwargs)
report = kwargs['instance']
kwargs['params_data'] = self.get_params_context(report)
@ -496,7 +499,9 @@ class ReportOutputView(ExportMasterView):
resulting :class:`rattail:~rattail.db.model.reports.ReportOutput`
object.
"""
session = RattailSession()
app = self.get_rattail_app()
model = self.model
session = app.make_session()
user = session.get(model.User, user_uuid)
try:
output = self.report_handler.generate_output(session, report, params, user, progress=progress)
@ -603,7 +608,7 @@ class ProblemReportView(MasterView):
]
def __init__(self, request):
super(ProblemReportView, self).__init__(request)
super().__init__(request)
app = self.get_rattail_app()
self.problem_handler = app.get_problem_report_handler()
@ -660,7 +665,7 @@ class ProblemReportView(MasterView):
return ProblemReportSchema()
def configure_form(self, f):
super(ProblemReportView, self).configure_form(f)
super().configure_form(f)
# email_*
if self.editing:
@ -703,10 +708,10 @@ class ProblemReportView(MasterView):
g = self.get_grid_factory()('days', [],
columns=['weekday_name', 'enabled'],
labels={'weekday_name': "Weekday"})
return HTML.literal(g.render_buefy_table_element(data_prop='weekdaysData'))
return HTML.literal(g.render_table_element(data_prop='weekdaysData'))
def template_kwargs_view(self, **kwargs):
kwargs = super(ProblemReportView, self).template_kwargs_view(**kwargs)
kwargs = super().template_kwargs_view(**kwargs)
report_info = kwargs['instance']
data = []

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2023 Lance Edgar
# Copyright © 2010-2024 Lance Edgar
#
# This file is part of Rattail.
#
@ -29,7 +29,7 @@ import os
from sqlalchemy import orm
from openpyxl.styles import Font, PatternFill
from rattail.db import model
from rattail.db.model import Role
from rattail.db.auth import administrator_role, guest_role, authenticated_role
from rattail.excel import ExcelWriter
@ -46,7 +46,7 @@ class RoleView(PrincipalMasterView):
"""
Master view for the Role model.
"""
model_class = model.Role
model_class = Role
has_versions = True
touchable = True
@ -77,7 +77,7 @@ class RoleView(PrincipalMasterView):
]
def configure_grid(self, g):
super(RoleView, self).configure_grid(g)
super().configure_grid(g)
# name
g.filters['name'].default_active = True
@ -158,6 +158,7 @@ class RoleView(PrincipalMasterView):
return True
def unique_name(self, node, value):
model = self.model
query = self.Session.query(model.Role)\
.filter(model.Role.name == value)
if self.editing:
@ -167,7 +168,7 @@ class RoleView(PrincipalMasterView):
raise colander.Invalid(node, "Name must be unique")
def configure_form(self, f):
super(RoleView, self).configure_form(f)
super().configure_form(f)
role = f.model_instance
app = self.get_rattail_app()
auth = app.get_auth_handler()
@ -265,7 +266,7 @@ class RoleView(PrincipalMasterView):
g.main_actions.append(self.make_action('edit', icon='edit'))
return HTML.literal(
g.render_buefy_table_element(data_prop='usersData'))
g.render_table_element(data_prop='usersData'))
def get_available_permissions(self):
"""
@ -322,7 +323,7 @@ class RoleView(PrincipalMasterView):
"""
if data is None:
data = form.validated
role = super(RoleView, self).objectify(form, data)
role = super().objectify(form, data)
self.update_permissions(role, data['permissions'])
return role
@ -345,6 +346,7 @@ class RoleView(PrincipalMasterView):
auth.revoke_permission(role, pkey)
def template_kwargs_view(self, **kwargs):
model = self.model
role = kwargs['instance']
if role.users:
users = sorted(role.users, key=lambda u: u.username)
@ -390,6 +392,7 @@ class RoleView(PrincipalMasterView):
def find_principals_with_permission(self, session, permission):
app = self.get_rattail_app()
model = self.model
auth = app.get_auth_handler()
# TODO: this should search Permission table instead, and work backward to Role?
@ -408,6 +411,7 @@ class RoleView(PrincipalMasterView):
Excel spreadsheet, and returns that file.
"""
app = self.get_rattail_app()
model = self.model
auth = app.get_auth_handler()
roles = self.Session.query(model.Role)\

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2023 Lance Edgar
# Copyright © 2010-2024 Lance Edgar
#
# This file is part of Rattail.
#
@ -32,8 +32,8 @@ from collections import OrderedDict
import json
from rattail.db import model
from rattail.settings import Setting
from rattail.db.model import Setting
from rattail.settings import Setting as AppSetting
from rattail.util import import_module_path
import colander
@ -81,7 +81,7 @@ class AppInfoView(MasterView):
return data
def configure_grid(self, g):
super(AppInfoView, self).configure_grid(g)
super().configure_grid(g)
g.sorters['name'] = g.make_simple_sorter('name', foldcase=True)
g.set_sort_defaults('name')
@ -94,12 +94,12 @@ class AppInfoView(MasterView):
g.set_searchable('editable_project_location')
def template_kwargs_index(self, **kwargs):
kwargs = super(AppInfoView, self).template_kwargs_index(**kwargs)
kwargs = super().template_kwargs_index(**kwargs)
kwargs['configure_button_title'] = "Configure App"
return kwargs
def configure_get_context(self, **kwargs):
context = super(AppInfoView, self).configure_get_context(**kwargs)
context = super().configure_get_context(**kwargs)
weblibs = OrderedDict([
('vue', "Vue"),
@ -195,7 +195,7 @@ class SettingView(MasterView):
"""
Master view for the settings model.
"""
model_class = model.Setting
model_class = Setting
model_title = "Raw Setting"
model_title_plural = "Raw Settings"
bulk_deletable = True
@ -207,18 +207,19 @@ class SettingView(MasterView):
]
def configure_grid(self, g):
super(SettingView, self).configure_grid(g)
super().configure_grid(g)
g.filters['name'].default_active = True
g.filters['name'].default_verb = 'contains'
g.set_sort_defaults('name')
g.set_link('name')
def configure_form(self, f):
super(SettingView, self).configure_form(f)
super().configure_form(f)
if self.creating:
f.set_validator('name', self.unique_name)
def unique_name(self, node, value):
model = self.model
setting = self.Session.get(model.Setting, value)
if setting:
raise colander.Invalid(node, "Setting name must be unique")
@ -245,7 +246,7 @@ class SettingView(MasterView):
self.rattail_config.beaker_invalidate_setting(setting.name)
# otherwise delete like normal
super(SettingView, self).delete_instance(setting)
super().delete_instance(setting)
# TODO: deprecate / remove this
@ -307,14 +308,14 @@ class AppSettingsView(View):
'settings': settings,
'config_options': config_options,
}
context['buefy_data'] = self.get_buefy_data(form, groups, settings)
context['settings_data'] = self.get_settings_data(form, groups, settings)
# TODO: this seems hacky, and probably only needed if theme changes?
if current_group == '(All)':
current_group = ''
context['current_group'] = current_group
return context
def get_buefy_data(self, form, groups, settings):
def get_settings_data(self, form, groups, settings):
dform = form.make_deform_form()
grouped = dict([(label, [])
for label in groups])
@ -407,7 +408,7 @@ class AppSettingsView(View):
module = import_module_path(module)
for name in dir(module):
obj = getattr(module, name)
if isinstance(obj, type) and issubclass(obj, Setting) and obj is not Setting:
if isinstance(obj, type) and issubclass(obj, AppSetting) and obj is not AppSetting:
if core_only and not obj.core:
continue
# NOTE: we set this here, and reference it elsewhere

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2023 Lance Edgar
# Copyright © 2010-2024 Lance Edgar
#
# This file is part of Rattail.
#
@ -28,9 +28,8 @@ import datetime
import sqlalchemy as sa
from rattail import enum
from rattail.db import model, api
from rattail.time import localtime, make_utc, get_sunday
from rattail.db import api
from rattail.time import get_sunday
from rattail.util import hours_as_decimal
import colander
@ -83,6 +82,8 @@ class TimeSheetView(View):
"""
Determine date/store/dept context from user's session and/or defaults.
"""
app = self.get_rattail_app()
model = self.model
date = None
date_key = 'timesheet.{}.date'.format(self.key)
if date_key in self.request.session:
@ -93,7 +94,7 @@ class TimeSheetView(View):
except ValueError:
pass
if not date:
date = localtime(self.rattail_config).date()
date = app.today()
store = None
department = None
@ -113,7 +114,7 @@ class TimeSheetView(View):
store = api.get_store(Session(), store)
employees = Session.query(model.Employee)\
.filter(model.Employee.status == enum.EMPLOYEE_STATUS_CURRENT)
.filter(model.Employee.status == self.enum.EMPLOYEE_STATUS_CURRENT)
if store:
employees = employees.join(model.EmployeeStore)\
.filter(model.EmployeeStore.store == store)
@ -132,6 +133,8 @@ class TimeSheetView(View):
"""
Determine employee/date context from user's session and/or defaults
"""
app = self.get_rattail_app()
model = self.model
date = None
date_key = 'timesheet.{}.employee.date'.format(self.key)
if date_key in self.request.session:
@ -142,7 +145,7 @@ class TimeSheetView(View):
except ValueError:
pass
if not date:
date = localtime(self.rattail_config).date()
date = app.today()
employee = None
employee_key = 'timesheet.{}.employee'.format(self.key)
@ -191,7 +194,7 @@ class TimeSheetView(View):
stores = self.get_stores()
store_values = [(s.uuid, "{} - {}".format(s.id, s.name)) for s in stores]
store_values.insert(0, ('', "(all)"))
form.set_widget('store', forms.widgets.PlainSelectWidget(values=store_values))
form.set_widget('store', dfwidget.SelectWidget(values=store_values))
if context['store']:
form.set_default('store', context['store'].uuid)
else:
@ -203,7 +206,7 @@ class TimeSheetView(View):
departments = self.get_departments()
department_values = [(d.uuid, d.name) for d in departments]
department_values.insert(0, ('', "(all)"))
form.set_widget('department', forms.widgets.PlainSelectWidget(values=department_values))
form.set_widget('department', dfwidget.SelectWidget(values=department_values))
if context['department']:
form.set_default('department', context['department'].uuid)
else:
@ -292,6 +295,7 @@ class TimeSheetView(View):
self.request.session['timesheet.{}.{}'.format(mainkey, key)] = value
def get_stores(self):
model = self.model
return Session.query(model.Store).order_by(model.Store.id).all()
def get_store_options(self, stores):
@ -299,6 +303,7 @@ class TimeSheetView(View):
return tags.Options(options, prompt="(all)")
def get_departments(self):
model = self.model
return Session.query(model.Department).order_by(model.Department.name).all()
def get_department_options(self, departments):
@ -402,6 +407,7 @@ class TimeSheetView(View):
the given params. The cached shift data is attached to each employee.
"""
app = self.get_rattail_app()
model = self.model
# TODO: a bit hacky, this? display hours as HH:MM by default, but
# check config in order to display as HH.HH for certain users
@ -413,19 +419,19 @@ class TimeSheetView(View):
hours_style = 'pretty'
shift_type = 'scheduled' if cls is model.ScheduledShift else 'worked'
min_time = localtime(self.rattail_config, datetime.datetime.combine(weekdays[0], datetime.time(0)))
max_time = localtime(self.rattail_config, datetime.datetime.combine(weekdays[-1] + datetime.timedelta(days=1), datetime.time(0)))
min_time = app.localtime(datetime.datetime.combine(weekdays[0], datetime.time(0)))
max_time = app.localtime(datetime.datetime.combine(weekdays[-1] + datetime.timedelta(days=1), datetime.time(0)))
shifts = Session.query(cls)\
.filter(cls.employee_uuid.in_([e.uuid for e in employees]))\
.filter(sa.or_(
sa.and_(
cls.start_time >= make_utc(min_time),
cls.start_time < make_utc(max_time),
cls.start_time >= app.make_utc(min_time),
cls.start_time < app.make_utc(max_time),
),
sa.and_(
cls.start_time == None,
cls.end_time >= make_utc(min_time),
cls.end_time < make_utc(max_time),
cls.end_time >= app.make_utc(min_time),
cls.end_time < app.make_utc(max_time),
)))\
.all()

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2023 Lance Edgar
# Copyright © 2010-2024 Lance Edgar
#
# This file is part of Rattail.
#
@ -80,7 +80,7 @@ class TableView(MasterView):
]
def __init__(self, request):
super(TableView, self).__init__(request)
super().__init__(request)
app = self.get_rattail_app()
self.db_handler = app.get_db_handler()
@ -102,7 +102,7 @@ class TableView(MasterView):
for row in result]
def configure_grid(self, g):
super(TableView, self).configure_grid(g)
super().configure_grid(g)
# table_name
g.sorters['table_name'] = g.make_simple_sorter('table_name', foldcase=True)
@ -114,7 +114,7 @@ class TableView(MasterView):
g.sorters['row_count'] = g.make_simple_sorter('row_count')
def configure_form(self, f):
super(TableView, self).configure_form(f)
super().configure_form(f)
# TODO: should render this instead, by inspecting table
if not self.creating:
@ -169,7 +169,7 @@ class TableView(MasterView):
return TableSchema()
def get_xref_buttons(self, table):
buttons = super(TableView, self).get_xref_buttons(table)
buttons = super().get_xref_buttons(table)
if table.get('model_name'):
all_views = self.request.registry.settings['tailbone_model_views']
@ -182,15 +182,15 @@ class TableView(MasterView):
if self.request.has_perm('model_views.create'):
url = self.request.route_url('model_views.create',
_query={'model_name': table['model_name']})
buttons.append(self.make_buefy_button("New View",
is_primary=True,
url=url,
icon_left='plus'))
buttons.append(self.make_button("New View",
is_primary=True,
url=url,
icon_left='plus'))
return buttons
def template_kwargs_create(self, **kwargs):
kwargs = super(TableView, self).template_kwargs_create(**kwargs)
kwargs = super().template_kwargs_create(**kwargs)
app = self.get_rattail_app()
model = self.model
@ -301,7 +301,7 @@ class TableView(MasterView):
return data
def configure_row_grid(self, g):
super(TableView, self).configure_row_grid(g)
super().configure_row_grid(g)
g.sorters['sequence'] = g.make_simple_sorter('sequence')
g.set_sort_defaults('sequence')
@ -419,7 +419,7 @@ class TablesView(TableView):
def __init__(self, request):
warnings.warn("TablesView is deprecated; please use TableView instead",
DeprecationWarning, stacklevel=2)
super(TablesView, self).__init__(request)
super().__init__(request)
class TableSchema(colander.Schema):

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2023 Lance Edgar
# Copyright © 2010-2024 Lance Edgar
#
# This file is part of Rattail.
#
@ -98,4 +98,4 @@ class MasterView(views.MasterView):
main_actions=actions,
)
return HTML.literal(
g.render_buefy_table_element(data_prop='probesData'))
g.render_table_element(data_prop='probesData'))

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2023 Lance Edgar
# Copyright © 2010-2024 Lance Edgar
#
# This file is part of Rattail.
#
@ -202,7 +202,7 @@ class TransactionView(MasterView):
return 'warning'
def configure_form(self, f):
super(TransactionView, self).configure_form(f)
super().configure_form(f)
# system
f.set_enum('system', self.enum.TRAINWRECK_SYSTEM)
@ -240,10 +240,10 @@ class TransactionView(MasterView):
request=self.request)
return HTML.literal(
g.render_buefy_table_element(data_prop='custorderXrefMarkersData'))
g.render_table_element(data_prop='custorderXrefMarkersData'))
def template_kwargs_view(self, **kwargs):
kwargs = super(TransactionView, self).template_kwargs_view(**kwargs)
kwargs = super().template_kwargs_view(**kwargs)
form = kwargs['form']
if 'custorder_xref_markers' in form:
@ -266,7 +266,7 @@ class TransactionView(MasterView):
return item.transaction
def configure_row_grid(self, g):
super(TransactionView, self).configure_row_grid(g)
super().configure_row_grid(g)
g.set_sort_defaults('sequence')
g.set_type('unit_quantity', 'quantity')
@ -286,7 +286,7 @@ class TransactionView(MasterView):
return "Trainwreck Line Item"
def configure_row_form(self, f):
super(TransactionView, self).configure_row_form(f)
super().configure_row_form(f)
# transaction
f.set_renderer('transaction', self.render_transaction)
@ -325,7 +325,7 @@ class TransactionView(MasterView):
request=self.request)
return HTML.literal(
g.render_buefy_table_element(data_prop='discountsData'))
g.render_table_element(data_prop='discountsData'))
def template_kwargs_view_row(self, **kwargs):
form = kwargs['form']
@ -401,7 +401,7 @@ class TransactionView(MasterView):
]
def configure_get_context(self):
context = super(TransactionView, self).configure_get_context()
context = super().configure_get_context()
app = self.get_rattail_app()
trainwreck_handler = app.get_trainwreck_handler()
@ -415,7 +415,7 @@ class TransactionView(MasterView):
return context
def configure_gather_settings(self, data):
settings = super(TransactionView, self).configure_gather_settings(data)
settings = super().configure_gather_settings(data)
app = self.get_rattail_app()
trainwreck_handler = app.get_trainwreck_handler()
@ -432,7 +432,7 @@ class TransactionView(MasterView):
return settings
def configure_remove_settings(self):
super(TransactionView, self).configure_remove_settings()
super().configure_remove_settings()
app = self.get_rattail_app()
names = [

View file

@ -2,7 +2,7 @@
################################################################################
#
# Rattail -- Retail Software Framework
# Copyright © 2010-2023 Lance Edgar
# Copyright © 2010-2024 Lance Edgar
#
# This file is part of Rattail.
#
@ -84,7 +84,7 @@ class UserView(PrincipalMasterView):
]
def __init__(self, request):
super(UserView, self).__init__(request)
super().__init__(request)
app = self.get_rattail_app()
# always get a reference to the auth/merge handler
@ -92,7 +92,7 @@ class UserView(PrincipalMasterView):
self.merge_handler = self.auth_handler
def query(self, session):
query = super(UserView, self).query(session)
query = super().query(session)
model = self.model
# bring in the related Person(s)
@ -102,7 +102,7 @@ class UserView(PrincipalMasterView):
return query
def configure_grid(self, g):
super(UserView, self).configure_grid(g)
super().configure_grid(g)
model = self.model
del g.filters['salt']
@ -177,7 +177,7 @@ class UserView(PrincipalMasterView):
raise colander.Invalid(node, "Person not found (you must *select* a record)")
def configure_form(self, f):
super(UserView, self).configure_form(f)
super().configure_form(f)
model = self.model
user = f.model_instance
@ -290,12 +290,12 @@ class UserView(PrincipalMasterView):
self.make_action('delete', icon='trash',
click_handler="$emit('api-token-delete', props.row)")])
button = self.make_buefy_button("New", is_primary=True,
icon_left='plus',
**{'@click': "$emit('api-new-token')"})
button = self.make_button("New", is_primary=True,
icon_left='plus',
**{'@click': "$emit('api-new-token')"})
table = HTML.literal(
g.render_buefy_table_element(data_prop='apiTokens'))
g.render_table_element(data_prop='apiTokens'))
return HTML.tag('div', c=[button, table])
@ -329,7 +329,7 @@ class UserView(PrincipalMasterView):
'tokens': self.get_api_tokens(user)}
def template_kwargs_view(self, **kwargs):
kwargs = super(UserView, self).template_kwargs_view(**kwargs)
kwargs = super().template_kwargs_view(**kwargs)
user = kwargs['instance']
kwargs['api_tokens_data'] = self.get_api_tokens(user)
@ -377,7 +377,7 @@ class UserView(PrincipalMasterView):
# create/update user as per normal
if data is None:
data = form.validated
user = super(UserView, self).objectify(form, data)
user = super().objectify(form, data)
# create/update person as needed
names = {}
@ -487,7 +487,7 @@ class UserView(PrincipalMasterView):
.filter(model.UserEvent.user == user)
def configure_row_grid(self, g):
super(UserView, self).configure_row_grid(g)
super().configure_row_grid(g)
g.width = 'half'
g.filterable = False
g.set_sort_defaults('occurred', 'desc')
@ -588,7 +588,7 @@ class UserView(PrincipalMasterView):
'themes.style.{}'.format(name))
if css:
options.append({'value': css, 'label': name})
context['buefy_css_options'] = options
context['theme_style_options'] = options
return context
@ -699,12 +699,12 @@ class UserEventView(MasterView):
]
def get_data(self, session=None):
query = super(UserEventView, self).get_data(session=session)
query = super().get_data(session=session)
model = self.model
return query.join(model.User)
def configure_grid(self, g):
super(UserEventView, self).configure_grid(g)
super().configure_grid(g)
model = self.model
g.set_joiner('person', lambda q: q.outerjoin(model.Person))
g.set_sorter('user', model.User.username)