Improve shoppers/people display for Customer tab in profile view

also expose settings for people/clientele handlers
This commit is contained in:
Lance Edgar 2023-06-11 14:52:07 -05:00
parent 0d52d554e7
commit edd5d49e36
5 changed files with 112 additions and 14 deletions

View file

@ -62,6 +62,14 @@
</b-checkbox> </b-checkbox>
</b-field> </b-field>
<b-field label="Clientele Handler"
message="Leave blank for default handler.">
<b-input name="rattail.clientele.handler"
v-model="simpleSettings['rattail.clientele.handler']"
@input="settingsNeedSaved = true">
</b-input>
</b-field>
</div> </div>
<h3 class="block is-size-3">POS</h3> <h3 class="block is-size-3">POS</h3>

View file

@ -15,6 +15,14 @@
</b-checkbox> </b-checkbox>
</b-field> </b-field>
<b-field label="People Handler"
message="Leave blank for default handler.">
<b-input name="rattail.people.handler"
v-model="simpleSettings['rattail.people.handler']"
@input="settingsNeedSaved = true">
</b-input>
</b-field>
</div> </div>
</%def> </%def>

View file

@ -697,25 +697,55 @@
{{ customer._key }} {{ customer._key }}
</b-field> </b-field>
<b-field horizontal label="Name"> <b-field horizontal label="Account Name">
{{ customer.name }} {{ customer.name }}
</b-field> </b-field>
<b-field horizontal label="People"> <b-field horizontal label="Account Holder">
<ul> <span v-if="customer.account_holder && customer.account_holder.uuid == person.uuid">
<li v-for="p in customer.people" {{ customer.account_holder.display_name }}
:key="p.uuid"> </span>
<a v-if="p.uuid != person.uuid" <a v-if="customer.account_holder && customer.account_holder.uuid != person.uuid"
:href="p.view_profile_url"> :href="customer.account_holder.view_profile_url">
{{ p.display_name }} {{ customer.account_holder.display_name }}
</a> </a>
<span v-if="p.uuid == person.uuid"> <span v-if="!customer.account_holder"></span>
{{ p.display_name }}
</span>
</li>
</ul>
</b-field> </b-field>
% if expose_customer_shoppers:
<b-field horizontal label="Shoppers">
<ul>
<li v-for="shopper in customer.shoppers"
:key="shopper.uuid">
<a v-if="shopper.person_uuid != person.uuid"
:href="shopper.view_profile_url">
{{ shopper.display_name }}
</a>
<span v-if="shopper.person_uuid == person.uuid">
{{ shopper.display_name }}
</span>
</li>
</ul>
</b-field>
% endif
% if expose_customer_people:
<b-field horizontal label="People">
<ul>
<li v-for="p in customer.people"
:key="p.uuid">
<a v-if="p.uuid != person.uuid"
:href="p.view_profile_url">
{{ p.display_name }}
</a>
<span v-if="p.uuid == person.uuid">
{{ p.display_name }}
</span>
</li>
</ul>
</b-field>
% endif
<b-field horizontal label="Address" <b-field horizontal label="Address"
v-for="address in customer.addresses" v-for="address in customer.addresses"
:key="address.uuid"> :key="address.uuid">

View file

@ -57,6 +57,7 @@ class CustomerView(MasterView):
labels = { labels = {
'id': "ID", 'id': "ID",
'name': "Account Name",
'default_phone': "Phone Number", 'default_phone': "Phone Number",
'default_email': "Email Address", 'default_email': "Email Address",
'default_address': "Physical Address", 'default_address': "Physical Address",
@ -74,6 +75,7 @@ class CustomerView(MasterView):
form_fields = [ form_fields = [
'_customer_key_', '_customer_key_',
'name', 'name',
'account_holder',
'default_phone', 'default_phone',
'default_address', 'default_address',
'address_street', 'address_street',
@ -111,11 +113,13 @@ class CustomerView(MasterView):
default=False) default=False)
return self._expose_active_in_pos return self._expose_active_in_pos
# TODO: this is duplicated in people view module
def should_expose_shoppers(self): def should_expose_shoppers(self):
return self.rattail_config.getbool('rattail', return self.rattail_config.getbool('rattail',
'customers.expose_shoppers', 'customers.expose_shoppers',
default=True) default=True)
# TODO: this is duplicated in people view module
def should_expose_people(self): def should_expose_people(self):
return self.rattail_config.getbool('rattail', return self.rattail_config.getbool('rattail',
'customers.expose_people', 'customers.expose_people',
@ -249,6 +253,13 @@ class CustomerView(MasterView):
customer = f.model_instance customer = f.model_instance
permission_prefix = self.get_permission_prefix() permission_prefix = self.get_permission_prefix()
# account_holder
if self.creating:
f.remove_field('account_holder')
else:
f.set_readonly('account_holder')
f.set_renderer('account_holder', self.render_person)
# default_email # default_email
f.set_renderer('default_email', self.render_default_email) f.set_renderer('default_email', self.render_default_email)
if not self.creating and customer.emails: if not self.creating and customer.emails:
@ -623,6 +634,8 @@ class CustomerView(MasterView):
'option': 'customers.expose_people', 'option': 'customers.expose_people',
'type': bool, 'type': bool,
'default': True}, 'default': True},
{'section': 'rattail',
'option': 'clientele.handler'},
# POS # POS
{'section': 'rattail', {'section': 'rattail',

View file

@ -446,6 +446,8 @@ class PersonView(MasterView):
'customers_data': self.get_context_customers(person), 'customers_data': self.get_context_customers(person),
# TODO: deprecate / remove this # TODO: deprecate / remove this
'customer_xref_buttons': self.get_customer_xref_buttons(person), 'customer_xref_buttons': self.get_customer_xref_buttons(person),
'expose_customer_people': self.customers_should_expose_people(),
'expose_customer_shoppers': self.customers_should_expose_shoppers(),
'members_data': self.get_context_members(person), 'members_data': self.get_context_members(person),
'member_xref_buttons': self.get_member_xref_buttons(person), 'member_xref_buttons': self.get_member_xref_buttons(person),
'employee': employee, 'employee': employee,
@ -554,6 +556,20 @@ class PersonView(MasterView):
return context return context
def get_context_shopper(self, shopper):
person = shopper.person
return {
'uuid': shopper.uuid,
'person_uuid': person.uuid,
'first_name': person.first_name,
'middle_name': person.middle_name,
'last_name': person.last_name,
'display_name': person.display_name,
'view_profile_url': self.get_action_url('view_profile', person),
'phones': self.get_context_phones(person),
'emails': self.get_context_emails(person),
}
def get_context_content_title(self, person): def get_context_content_title(self, person):
return str(person) return str(person)
@ -578,6 +594,7 @@ class PersonView(MasterView):
def get_context_customers(self, person): def get_context_customers(self, person):
app = self.get_rattail_app() app = self.get_rattail_app()
clientele = app.get_clientele_handler() clientele = app.get_clientele_handler()
expose_shoppers = self.customers_should_expose_shoppers()
customers = clientele.get_customers_for_account_holder(person) customers = clientele.get_customers_for_account_holder(person)
key = self.get_customer_key_field() key = self.get_customer_key_field()
@ -599,6 +616,14 @@ class PersonView(MasterView):
'external_links': [], 'external_links': [],
} }
if customer.account_holder:
context['account_holder'] = self.get_context_person(
customer.account_holder)
if expose_shoppers:
context['shoppers'] = [self.get_context_shopper(s)
for s in customer.shoppers]
for supp in self.iter_view_supplements(): for supp in self.iter_view_supplements():
if hasattr(supp, 'get_context_for_customer'): if hasattr(supp, 'get_context_for_customer'):
context = supp.get_context_for_customer(customer, context) context = supp.get_context_for_customer(customer, context)
@ -607,6 +632,18 @@ class PersonView(MasterView):
return data return data
# TODO: this is duplicated in customers view module
def customers_should_expose_shoppers(self):
return self.rattail_config.getbool('rattail',
'customers.expose_shoppers',
default=True)
# TODO: this is duplicated in customers view module
def customers_should_expose_people(self):
return self.rattail_config.getbool('rattail',
'customers.expose_people',
default=True)
def get_context_members(self, person): def get_context_members(self, person):
app = self.get_rattail_app() app = self.get_rattail_app()
membership = app.get_membership_handler() membership = app.get_membership_handler()
@ -1394,6 +1431,8 @@ class PersonView(MasterView):
{'section': 'rattail', {'section': 'rattail',
'option': 'people.straight_to_profile', 'option': 'people.straight_to_profile',
'type': bool}, 'type': bool},
{'section': 'rattail',
'option': 'people.handler'},
] ]