Add support for "configured customer/member key"

also improve product key support, same patterns
This commit is contained in:
Lance Edgar 2023-06-06 11:06:16 -05:00
parent 9b59b44609
commit 0d97ff2936
7 changed files with 224 additions and 39 deletions

View file

@ -6,6 +6,26 @@
<h3 class="block is-size-3">General</h3> <h3 class="block is-size-3">General</h3>
<div class="block" style="padding-left: 2rem;"> <div class="block" style="padding-left: 2rem;">
<b-field grouped>
<b-field label="Key Field">
<b-select name="rattail.customers.key_field"
v-model="simpleSettings['rattail.customers.key_field']"
@input="updateKeyLabel()">
<option value="id">id</option>
<option value="number">number</option>
</b-select>
</b-field>
<b-field label="Key Field Label">
<b-input name="rattail.customers.key_label"
v-model="simpleSettings['rattail.customers.key_label']"
@input="settingsNeedSaved = true">
</b-input>
</b-field>
</b-field>
<b-field message="If not set, customer chooser is an autocomplete field."> <b-field message="If not set, customer chooser is an autocomplete field.">
<b-checkbox name="rattail.customers.choice_uses_dropdown" <b-checkbox name="rattail.customers.choice_uses_dropdown"
v-model="simpleSettings['rattail.customers.choice_uses_dropdown']" v-model="simpleSettings['rattail.customers.choice_uses_dropdown']"
@ -33,5 +53,29 @@
</%def> </%def>
<%def name="modify_this_page_vars()">
${parent.modify_this_page_vars()}
<script type="text/javascript">
ThisPage.methods.getLabelForKey = function(key) {
switch (key) {
case 'id':
return "ID"
case 'number':
return "Number"
default:
return "Key"
}
}
ThisPage.methods.updateKeyLabel = function() {
this.simpleSettings['rattail.customers.key_label'] = this.getLabelForKey(
this.simpleSettings['rattail.customers.key_field'])
this.settingsNeedSaved = true
}
</script>
</%def>
${parent.body()} ${parent.body()}

View file

@ -0,0 +1,57 @@
## -*- coding: utf-8; -*-
<%inherit file="/configure.mako" />
<%def name="form_content()">
<h3 class="block is-size-3">General</h3>
<div class="block" style="padding-left: 2rem;">
<b-field grouped>
<b-field label="Key Field">
<b-select name="rattail.members.key_field"
v-model="simpleSettings['rattail.members.key_field']"
@input="updateKeyLabel()">
<option value="id">id</option>
<option value="number">number</option>
</b-select>
</b-field>
<b-field label="Key Field Label">
<b-input name="rattail.members.key_label"
v-model="simpleSettings['rattail.members.key_label']"
@input="settingsNeedSaved = true">
</b-input>
</b-field>
</b-field>
</div>
</%def>
<%def name="modify_this_page_vars()">
${parent.modify_this_page_vars()}
<script type="text/javascript">
ThisPage.methods.getLabelForKey = function(key) {
switch (key) {
case 'id':
return "ID"
case 'number':
return "Number"
default:
return "Key"
}
}
ThisPage.methods.updateKeyLabel = function() {
this.simpleSettings['rattail.members.key_label'] = this.getLabelForKey(
this.simpleSettings['rattail.members.key_field'])
this.settingsNeedSaved = true
}
</script>
</%def>
${parent.body()}

View file

@ -540,19 +540,15 @@
<b-icon pack="fas" <b-icon pack="fas"
icon="caret-right"> icon="caret-right">
</b-icon> </b-icon>
<strong>#{{ member.number }} {{ member.display }}</strong> <strong>{{ member._key }} - {{ member.display }}</strong>
</div> </div>
<div class="panel-block"> <div class="panel-block">
<div style="display: flex; justify-content: space-between; width: 100%;"> <div style="display: flex; justify-content: space-between; width: 100%;">
<div style="flex-grow: 1;"> <div style="flex-grow: 1;">
<b-field horizontal label="Number"> <b-field horizontal label="${member_key_label}">
{{ member.number }} {{ member._key }}
</b-field>
<b-field horizontal label="ID">
{{ member.id }}
</b-field> </b-field>
<b-field horizontal label="Active"> <b-field horizontal label="Active">
@ -630,19 +626,15 @@
<b-icon pack="fas" <b-icon pack="fas"
icon="caret-right"> icon="caret-right">
</b-icon> </b-icon>
<strong>#{{ customer.number }} {{ customer.name }}</strong> <strong>{{ customer._key }} - {{ customer.name }}</strong>
</div> </div>
<div class="panel-block"> <div class="panel-block">
<div style="display: flex; justify-content: space-between; width: 100%;"> <div style="display: flex; justify-content: space-between; width: 100%;">
<div style="flex-grow: 1;"> <div style="flex-grow: 1;">
<b-field horizontal label="Number"> <b-field horizontal label="${customer_key_label}">
{{ customer.number }} {{ customer._key }}
</b-field>
<b-field horizontal label="ID">
{{ customer.id }}
</b-field> </b-field>
<b-field horizontal label="Name"> <b-field horizontal label="Name">
@ -1011,8 +1003,8 @@
<%def name="render_profile_tabs()"> <%def name="render_profile_tabs()">
${self.render_personal_tab()} ${self.render_personal_tab()}
${self.render_customer_tab()}
${self.render_member_tab()} ${self.render_member_tab()}
${self.render_customer_tab()}
${self.render_employee_tab()} ${self.render_employee_tab()}
${self.render_user_tab()} ${self.render_user_tab()}
</%def> </%def>

View file

@ -63,16 +63,14 @@ class CustomerView(MasterView):
} }
grid_columns = [ grid_columns = [
'id', '_customer_key_',
'number',
'name', 'name',
'phone', 'phone',
'email', 'email',
] ]
form_fields = [ form_fields = [
'id', '_customer_key_',
'number',
'name', 'name',
'default_phone', 'default_phone',
'default_address', 'default_address',
@ -114,13 +112,16 @@ class CustomerView(MasterView):
super(CustomerView, self).configure_grid(g) super(CustomerView, self).configure_grid(g)
model = self.model model = self.model
# number # customer key
g.set_link('number') field = self.get_customer_key_field()
g.filters[field].default_active = True
g.filters[field].default_verb = 'equal'
g.set_sort_defaults(field)
g.set_link(field)
# name # name
g.filters['name'].default_active = True g.filters['name'].default_active = True
g.filters['name'].default_verb = 'contains' g.filters['name'].default_verb = 'contains'
g.set_sort_defaults('name')
# phone # phone
g.set_joiner('phone', lambda q: q.outerjoin(model.CustomerPhoneNumber, sa.and_( g.set_joiner('phone', lambda q: q.outerjoin(model.CustomerPhoneNumber, sa.and_(
@ -158,7 +159,6 @@ class CustomerView(MasterView):
g.filters['active_in_pos'].default_active = True g.filters['active_in_pos'].default_active = True
g.filters['active_in_pos'].default_verb = 'is_true' g.filters['active_in_pos'].default_verb = 'is_true'
g.set_link('id')
g.set_link('name') g.set_link('name')
g.set_link('person') g.set_link('person')
g.set_link('email') g.set_link('email')
@ -485,6 +485,10 @@ class CustomerView(MasterView):
return [ return [
# General # General
{'section': 'rattail',
'option': 'customers.key_field'},
{'section': 'rattail',
'option': 'customers.key_label'},
{'section': 'rattail', {'section': 'rattail',
'option': 'customers.choice_uses_dropdown', 'option': 'customers.choice_uses_dropdown',
'type': bool}, 'type': bool},

View file

@ -163,6 +163,8 @@ class MasterView(View):
labels = {'uuid': "UUID"} labels = {'uuid': "UUID"}
customer_key_fields = {}
member_key_fields = {}
product_key_fields = {} product_key_fields = {}
# ROW-RELATED ATTRS FOLLOW: # ROW-RELATED ATTRS FOLLOW:
@ -463,6 +465,8 @@ class MasterView(View):
grid.remove('local_only') grid.remove('local_only')
grid.remove_filter('local_only') grid.remove_filter('local_only')
self.configure_column_customer_key(grid)
self.configure_column_member_key(grid)
self.configure_column_product_key(grid) self.configure_column_product_key(grid)
for supp in self.iter_view_supplements(): for supp in self.iter_view_supplements():
@ -561,6 +565,8 @@ class MasterView(View):
# super(MasterView, self).configure_row_grid(grid) # super(MasterView, self).configure_row_grid(grid)
self.set_row_labels(grid) self.set_row_labels(grid)
self.configure_column_customer_key(grid)
self.configure_column_member_key(grid)
self.configure_column_product_key(grid) self.configure_column_product_key(grid)
def row_grid_extra_class(self, obj, i): def row_grid_extra_class(self, obj, i):
@ -2407,8 +2413,14 @@ class MasterView(View):
'quickie': None, 'quickie': None,
} }
key = self.rattail_config.product_key() context['customer_key_field'] = self.get_customer_key_field()
context['product_key_field'] = self.product_key_fields.get(key, key) context['customer_key_label'] = self.get_customer_key_label()
context['member_key_field'] = self.get_member_key_field()
context['member_key_label'] = self.get_member_key_label()
context['product_key_field'] = self.get_product_key_field()
context['product_key_label'] = self.get_product_key_label()
if self.expose_quickie_search: if self.expose_quickie_search:
context['quickie'] = self.get_quickie_context() context['quickie'] = self.get_quickie_context()
@ -4131,6 +4143,8 @@ class MasterView(View):
""" """
self.configure_common_form(form) self.configure_common_form(form)
self.configure_field_customer_key(form)
self.configure_field_member_key(form)
self.configure_field_product_key(form) self.configure_field_product_key(form)
for supp in self.iter_view_supplements(): for supp in self.iter_view_supplements():
@ -4596,6 +4610,8 @@ class MasterView(View):
self.set_row_labels(form) self.set_row_labels(form)
self.configure_field_customer_key(form)
self.configure_field_member_key(form)
self.configure_field_product_key(form) self.configure_field_product_key(form)
def validate_row_form(self, form): def validate_row_form(self, form):
@ -4604,23 +4620,77 @@ class MasterView(View):
return True return True
return False return False
def get_customer_key_field(self):
app = self.get_rattail_app()
key = app.get_customer_key_field()
return self.customer_key_fields.get(key, key)
def get_customer_key_label(self):
app = self.get_rattail_app()
field = self.get_customer_key_field()
return app.get_customer_key_label(field=field)
def configure_column_customer_key(self, g):
if '_customer_key_' in g.columns:
field = self.get_customer_key_field()
g.replace('_customer_key_', field)
g.set_label(field, self.get_customer_key_label())
g.set_link(field)
def configure_field_customer_key(self, f):
if '_customer_key_' in f:
field = self.get_customer_key_field()
f.replace('_customer_key_', field)
f.set_label(field, self.get_customer_key_label())
def get_member_key_field(self):
app = self.get_rattail_app()
key = app.get_member_key_field()
return self.member_key_fields.get(key, key)
def get_member_key_label(self):
app = self.get_rattail_app()
field = self.get_member_key_field()
return app.get_member_key_label(field=field)
def configure_column_member_key(self, g):
if '_member_key_' in g.columns:
field = self.get_member_key_field()
g.replace('_member_key_', field)
g.set_label(field, self.get_member_key_label())
g.set_link(field)
def configure_field_member_key(self, f):
if '_member_key_' in f:
field = self.get_member_key_field()
f.replace('_member_key_', field)
f.set_label(field, self.get_member_key_label())
def get_product_key_field(self):
app = self.get_rattail_app()
key = app.get_product_key_field()
return self.product_key_fields.get(key, key)
def get_product_key_label(self):
app = self.get_rattail_app()
field = self.get_product_key_field()
return app.get_product_key_label(field=field)
def configure_column_product_key(self, g): def configure_column_product_key(self, g):
if '_product_key_' in g.columns: if '_product_key_' in g.columns:
key = self.rattail_config.product_key() field = self.get_product_key_field()
field = self.product_key_fields.get(key, key)
g.replace('_product_key_', field) g.replace('_product_key_', field)
g.set_label(field, self.rattail_config.product_key_title(key)) g.set_label(field, self.get_product_key_label())
g.set_link(field) g.set_link(field)
if key == 'upc': if field == 'upc':
g.set_renderer(field, self.render_upc) g.set_renderer(field, self.render_upc)
def configure_field_product_key(self, f): def configure_field_product_key(self, f):
if '_product_key_' in f: if '_product_key_' in f:
key = self.rattail_config.product_key() field = self.get_product_key_field()
field = self.product_key_fields.get(key, key)
f.replace('_product_key_', field) f.replace('_product_key_', field)
f.set_label(field, self.rattail_config.product_key_title(key)) f.set_label(field, self.get_product_key_label())
if key == 'upc': if field == 'upc':
f.set_renderer(field, self.render_upc) f.set_renderer(field, self.render_upc)
def get_row_action_url(self, action, row, **kwargs): def get_row_action_url(self, action, row, **kwargs):

View file

@ -42,14 +42,14 @@ class MemberView(MasterView):
is_contact = True is_contact = True
touchable = True touchable = True
has_versions = True has_versions = True
configurable = True
labels = { labels = {
'id': "ID", 'id': "ID",
} }
grid_columns = [ grid_columns = [
'number', '_member_key_',
'id',
'person', 'person',
'customer', 'customer',
'email', 'email',
@ -61,8 +61,7 @@ class MemberView(MasterView):
] ]
form_fields = [ form_fields = [
'number', '_member_key_',
'id',
'person', 'person',
'customer', 'customer',
'default_email', 'default_email',
@ -77,6 +76,13 @@ class MemberView(MasterView):
def configure_grid(self, g): def configure_grid(self, g):
super(MemberView, self).configure_grid(g) super(MemberView, self).configure_grid(g)
# member key
field = self.get_member_key_field()
g.filters[field].default_active = True
g.filters[field].default_verb = 'equal'
g.set_sort_defaults(field)
g.set_link(field)
g.set_joiner('person', lambda q: q.outerjoin(model.Person)) g.set_joiner('person', lambda q: q.outerjoin(model.Person))
g.set_sorter('person', model.Person.display_name) g.set_sorter('person', model.Person.display_name)
g.set_filter('person', model.Person.display_name) g.set_filter('person', model.Person.display_name)
@ -105,8 +111,6 @@ class MemberView(MasterView):
g.set_filter('email', model.MemberEmailAddress.address) g.set_filter('email', model.MemberEmailAddress.address)
g.set_label('email', "Email Address") g.set_label('email', "Email Address")
g.set_sort_defaults('number')
g.set_link('person') g.set_link('person')
g.set_link('customer') g.set_link('customer')
@ -186,6 +190,16 @@ class MemberView(MasterView):
if member.phones: if member.phones:
return member.phones[0].number return member.phones[0].number
def configure_get_simple_settings(self):
return [
# General
{'section': 'rattail',
'option': 'members.key_field'},
{'section': 'rattail',
'option': 'members.key_label'},
]
def defaults(config, **kwargs): def defaults(config, **kwargs):
base = globals() base = globals()

View file

@ -545,12 +545,14 @@ class PersonView(MasterView):
return context return context
def get_context_customers(self, person): def get_context_customers(self, person):
key = self.get_customer_key_field()
data = [] data = []
for cp in person._customers: for cp in person._customers:
customer = cp.customer customer = cp.customer
data.append({ data.append({
'uuid': customer.uuid, 'uuid': customer.uuid,
'ordinal': cp.ordinal, 'ordinal': cp.ordinal,
'_key': getattr(customer, key),
'id': customer.id, 'id': customer.id,
'number': customer.number, 'number': customer.number,
'name': customer.name, 'name': customer.name,
@ -582,8 +584,10 @@ class PersonView(MasterView):
profile_url = self.request.route_url('people.view_profile', profile_url = self.request.route_url('people.view_profile',
uuid=member.person_uuid) uuid=member.person_uuid)
key = self.get_member_key_field()
return { return {
'uuid': member.uuid, 'uuid': member.uuid,
'_key': getattr(member, key),
'number': member.number, 'number': member.number,
'id': member.id, 'id': member.id,
'active': member.active, 'active': member.active,