fix: add optional Transactions tab for profile view
showing Trainwreck data by default
This commit is contained in:
parent
b7d26b6b8c
commit
16bf13787d
|
@ -33,6 +33,20 @@
|
|||
</b-field>
|
||||
|
||||
</div>
|
||||
|
||||
<h3 class="block is-size-3">Profile View</h3>
|
||||
<div class="block" style="padding-left: 2rem; width: 50%;">
|
||||
|
||||
<b-field>
|
||||
<b-checkbox name="tailbone.people.profile.expose_transactions"
|
||||
v-model="simpleSettings['tailbone.people.profile.expose_transactions']"
|
||||
native-value="true"
|
||||
@input="settingsNeedSaved = true">
|
||||
Show tab for Customer POS Transactions
|
||||
</b-checkbox>
|
||||
</b-field>
|
||||
|
||||
</div>
|
||||
</%def>
|
||||
|
||||
|
||||
|
|
|
@ -1656,6 +1656,34 @@
|
|||
</${b}-tab-item>
|
||||
</%def>
|
||||
|
||||
% if expose_transactions:
|
||||
|
||||
<%def name="render_transactions_tab_template()">
|
||||
<script type="text/x-template" id="transactions-tab-template">
|
||||
<div>
|
||||
<transactions-grid
|
||||
ref="transactionsGrid"
|
||||
/>
|
||||
</div>
|
||||
</script>
|
||||
</%def>
|
||||
|
||||
<%def name="render_transactions_tab()">
|
||||
<${b}-tab-item label="Transactions"
|
||||
value="transactions"
|
||||
% if not request.use_oruga:
|
||||
icon-pack="fas"
|
||||
% endif
|
||||
icon="bars">
|
||||
<transactions-tab ref="tab_transactions"
|
||||
:person="person"
|
||||
@profile-changed="profileChanged" />
|
||||
</${b}-tab-item>
|
||||
</%def>
|
||||
|
||||
% endif
|
||||
|
||||
|
||||
<%def name="render_user_tab_template()">
|
||||
<script type="text/x-template" id="user-tab-template">
|
||||
<div>
|
||||
|
@ -1806,6 +1834,9 @@
|
|||
% endif
|
||||
${self.render_employee_tab()}
|
||||
${self.render_notes_tab()}
|
||||
% if expose_transactions:
|
||||
${self.render_transactions_tab()}
|
||||
% endif
|
||||
${self.render_user_tab()}
|
||||
</%def>
|
||||
|
||||
|
@ -1941,6 +1972,12 @@
|
|||
% endif
|
||||
${self.render_employee_tab_template()}
|
||||
${self.render_notes_tab_template()}
|
||||
|
||||
% if expose_transactions:
|
||||
${transactions_grid.render_complete(allow_save_defaults=False)|n}
|
||||
${self.render_transactions_tab_template()}
|
||||
% endif
|
||||
|
||||
${self.render_user_tab_template()}
|
||||
${self.render_profile_info_template()}
|
||||
</%def>
|
||||
|
@ -2824,6 +2861,49 @@
|
|||
</script>
|
||||
</%def>
|
||||
|
||||
% if expose_transactions:
|
||||
|
||||
<%def name="declare_transactions_tab_vars()">
|
||||
<script type="text/javascript">
|
||||
|
||||
let TransactionsTabData = {}
|
||||
|
||||
let TransactionsTab = {
|
||||
template: '#transactions-tab-template',
|
||||
mixins: [TabMixin, SimpleRequestMixin],
|
||||
props: {
|
||||
person: Object,
|
||||
},
|
||||
computed: {},
|
||||
methods: {
|
||||
|
||||
// nb. we override this completely, just tell the grid to refresh
|
||||
refreshTab() {
|
||||
this.refreshingTab = true
|
||||
this.$refs.transactionsGrid.loadAsyncData(null, () => {
|
||||
this.refreshed = Date.now()
|
||||
this.refreshingTab = false
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
</script>
|
||||
</%def>
|
||||
|
||||
<%def name="make_transactions_tab_component()">
|
||||
${self.declare_transactions_tab_vars()}
|
||||
<script type="text/javascript">
|
||||
|
||||
TransactionsTab.data = function() { return TransactionsTabData }
|
||||
Vue.component('transactions-tab', TransactionsTab)
|
||||
<% request.register_component('transactions-tab', 'TransactionsTab') %>
|
||||
|
||||
</script>
|
||||
</%def>
|
||||
|
||||
% endif
|
||||
|
||||
<%def name="declare_user_tab_vars()">
|
||||
<script type="text/javascript">
|
||||
|
||||
|
@ -3086,6 +3166,19 @@
|
|||
% endif
|
||||
${self.make_employee_tab_component()}
|
||||
${self.make_notes_tab_component()}
|
||||
|
||||
% if expose_transactions:
|
||||
<script type="text/javascript">
|
||||
|
||||
TransactionsGrid.data = function() { return TransactionsGridData }
|
||||
Vue.component('transactions-grid', TransactionsGrid)
|
||||
## TODO: why is this line not needed?
|
||||
## <% request.register_component('transactions-grid', 'TransactionsGrid') %>
|
||||
|
||||
</script>
|
||||
${self.make_transactions_tab_component()}
|
||||
% endif
|
||||
|
||||
${self.make_user_tab_component()}
|
||||
${self.make_profile_info_component()}
|
||||
</%def>
|
||||
|
|
|
@ -40,6 +40,7 @@ import colander
|
|||
from webhelpers2.html import HTML, tags
|
||||
|
||||
from tailbone import forms, grids
|
||||
from tailbone.db import TrainwreckSession
|
||||
from tailbone.views import MasterView
|
||||
from tailbone.util import raw_datetime
|
||||
|
||||
|
@ -487,13 +488,101 @@ class PersonView(MasterView):
|
|||
'expose_customer_shoppers': self.customers_should_expose_shoppers(),
|
||||
'max_one_member': app.get_membership_handler().max_one_per_person(),
|
||||
'use_preferred_first_name': self.people_handler.should_use_preferred_first_name(),
|
||||
'expose_transactions': self.should_expose_profile_transactions(),
|
||||
}
|
||||
|
||||
if context['expose_transactions']:
|
||||
context['transactions_grid'] = self.profile_transactions_grid(person, empty=True)
|
||||
|
||||
if self.request.has_perm('people_profile.view_versions'):
|
||||
context['revisions_grid'] = self.profile_revisions_grid(person)
|
||||
|
||||
return self.render_to_response('view_profile', context)
|
||||
|
||||
def should_expose_profile_transactions(self):
|
||||
return self.rattail_config.get_bool('tailbone.people.profile.expose_transactions',
|
||||
default=False)
|
||||
|
||||
def profile_transactions_grid(self, person, empty=False):
|
||||
app = self.get_rattail_app()
|
||||
trainwreck = app.get_trainwreck_handler()
|
||||
model = trainwreck.get_model()
|
||||
route_prefix = self.get_route_prefix()
|
||||
if empty:
|
||||
# TODO: surely there is a better way to have empty data..? but so
|
||||
# much logic depends on a query, can't just pass empty list here
|
||||
data = TrainwreckSession.query(model.Transaction)\
|
||||
.filter(model.Transaction.uuid == 'bogus')
|
||||
else:
|
||||
data = self.profile_transactions_query(person)
|
||||
factory = self.get_grid_factory()
|
||||
g = factory(
|
||||
f'{route_prefix}.profile.transactions.{person.uuid}',
|
||||
data,
|
||||
request=self.request,
|
||||
model_class=model.Transaction,
|
||||
ajax_data_url=self.get_action_url('view_profile_transactions', person),
|
||||
columns=[
|
||||
'start_time',
|
||||
'end_time',
|
||||
'system',
|
||||
'terminal_id',
|
||||
'receipt_number',
|
||||
'cashier_name',
|
||||
'customer_id',
|
||||
'customer_name',
|
||||
'total',
|
||||
],
|
||||
labels={
|
||||
'terminal_id': "Terminal",
|
||||
'customer_id': "Customer " + app.get_customer_key_label(),
|
||||
},
|
||||
filterable=True,
|
||||
sortable=True,
|
||||
pageable=True,
|
||||
default_sortkey='end_time',
|
||||
default_sortdir='desc',
|
||||
component='transactions-grid',
|
||||
)
|
||||
if self.request.has_perm('trainwreck.transactions.view'):
|
||||
url = lambda row, i: self.request.route_url('trainwreck.transactions.view',
|
||||
uuid=row.uuid)
|
||||
g.main_actions.append(grids.GridAction('view', icon='eye', url=url))
|
||||
g.load_settings()
|
||||
|
||||
g.set_enum('system', self.enum.TRAINWRECK_SYSTEM)
|
||||
g.set_type('total', 'currency')
|
||||
|
||||
return g
|
||||
|
||||
def profile_transactions_query(self, person):
|
||||
"""
|
||||
Method which must return the base query for the profile's POS
|
||||
Transactions grid data.
|
||||
"""
|
||||
app = self.get_rattail_app()
|
||||
customer = app.get_customer(person)
|
||||
|
||||
key_field = app.get_customer_key_field()
|
||||
customer_key = getattr(customer, key_field)
|
||||
if customer_key is not None:
|
||||
customer_key = str(customer_key)
|
||||
|
||||
trainwreck = app.get_trainwreck_handler()
|
||||
model = trainwreck.get_model()
|
||||
query = TrainwreckSession.query(model.Transaction)\
|
||||
.filter(model.Transaction.customer_id == customer_key)
|
||||
return query
|
||||
|
||||
def profile_transactions_data(self):
|
||||
"""
|
||||
AJAX view to return new sorted, filtered data for transactions
|
||||
grid within profile view.
|
||||
"""
|
||||
person = self.get_instance()
|
||||
grid = self.profile_transactions_grid(person)
|
||||
return grid.get_table_data()
|
||||
|
||||
def get_context_tabchecks(self, person):
|
||||
app = self.get_rattail_app()
|
||||
membership = app.get_membership_handler()
|
||||
|
@ -1605,6 +1694,11 @@ class PersonView(MasterView):
|
|||
{'section': 'rattail',
|
||||
'option': 'people.handler'},
|
||||
|
||||
|
||||
# Profile View
|
||||
{'section': 'tailbone',
|
||||
'option': 'people.profile.expose_transactions',
|
||||
'type': bool},
|
||||
]
|
||||
|
||||
@classmethod
|
||||
|
@ -1873,6 +1967,15 @@ class PersonView(MasterView):
|
|||
permission='people_profile.delete_note',
|
||||
renderer='json')
|
||||
|
||||
# profile - transactions data
|
||||
config.add_route(f'{route_prefix}.view_profile_transactions',
|
||||
f'{instance_url_prefix}/profile/transactions',
|
||||
request_method='GET')
|
||||
config.add_view(cls, attr='profile_transactions_data',
|
||||
route_name=f'{route_prefix}.view_profile_transactions',
|
||||
permission=f'{permission_prefix}.view_profile',
|
||||
renderer='json')
|
||||
|
||||
# make user for person
|
||||
config.add_route('{}.make_user'.format(route_prefix), '{}/make-user'.format(url_prefix),
|
||||
request_method='POST')
|
||||
|
|
Loading…
Reference in a new issue