Add support for detaching Person from Customer

This commit is contained in:
Lance Edgar 2018-01-24 23:53:12 -06:00
parent b8c6e95b73
commit 96e5c42795
2 changed files with 121 additions and 6 deletions

View file

@ -0,0 +1,21 @@
## -*- coding: utf-8; -*-
<%inherit file="/master/view.mako" />
<%def name="extra_javascript()">
${parent.extra_javascript()}
% if master.people_detachable and request.has_perm('{}.detach_person'.format(permission_prefix)):
<script type="text/javascript">
$(function() {
$('.people .grid .actions a.detach').click(function() {
if (! confirm("Are you sure you wish to detach this Person from the Customer?")) {
return false;
}
});
});
</script>
% endif
</%def>
${parent.body()}

View file

@ -37,6 +37,7 @@ from deform import widget as dfwidget
from pyramid.httpexceptions import HTTPNotFound from pyramid.httpexceptions import HTTPNotFound
from webhelpers2.html import HTML, tags from webhelpers2.html import HTML, tags
from tailbone import grids
from tailbone.db import Session from tailbone.db import Session
from tailbone.views import MasterView3 as MasterView, AutocompleteView from tailbone.views import MasterView3 as MasterView, AutocompleteView
@ -50,6 +51,7 @@ class CustomersView(MasterView):
model_class = model.Customer model_class = model.Customer
has_versions = True has_versions = True
supports_mobile = True supports_mobile = True
people_detachable = True
labels = { labels = {
'id': "ID", 'id': "ID",
@ -78,6 +80,7 @@ class CustomersView(MasterView):
'active_in_pos', 'active_in_pos',
'active_in_pos_sticky', 'active_in_pos_sticky',
'people', 'people',
'groups',
] ]
def configure_grid(self, g): def configure_grid(self, g):
@ -151,6 +154,11 @@ class CustomersView(MasterView):
def configure_form(self, f): def configure_form(self, f):
super(CustomersView, self).configure_form(f) super(CustomersView, self).configure_form(f)
customer = f.model_instance customer = f.model_instance
permission_prefix = self.get_permission_prefix()
# id
if not self.creating:
f.set_readonly('id')
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:
@ -160,6 +168,10 @@ class CustomersView(MasterView):
if not self.creating and customer.phones: if not self.creating and customer.phones:
f.set_default('default_phone', customer.phones[0].number) f.set_default('default_phone', customer.phones[0].number)
# default_address
if self.creating:
f.remove_field('default_address')
else:
f.set_renderer('default_address', self.render_default_address) f.set_renderer('default_address', self.render_default_address)
f.set_readonly('default_address') f.set_readonly('default_address')
@ -168,13 +180,21 @@ class CustomersView(MasterView):
preferences.insert(0, ('', "(no preference)")) preferences.insert(0, ('', "(no preference)"))
f.set_widget('email_preference', dfwidget.SelectWidget(values=preferences)) f.set_widget('email_preference', dfwidget.SelectWidget(values=preferences))
# people
if self.creating:
f.remove_field('people')
elif self.viewing and self.request.has_perm('{}.detach_person'.format(permission_prefix)):
f.set_renderer('people', self.render_people_removable)
else:
f.set_renderer('people', self.render_people) f.set_renderer('people', self.render_people)
f.set_readonly('people') f.set_readonly('people')
# groups
if self.creating: if self.creating:
f.remove_field('people') f.remove_field('groups')
else: else:
f.set_readonly('id') f.set_renderer('groups', self.render_groups)
f.set_readonly('groups')
# TODO: something like this should be supported for default_email, default_phone # TODO: something like this should be supported for default_email, default_phone
# def after_edit(self, customer): # def after_edit(self, customer):
@ -226,6 +246,46 @@ class CustomersView(MasterView):
items.append(HTML.tag('li', link)) items.append(HTML.tag('li', link))
return HTML.tag('ul', HTML.literal('').join(items)) return HTML.tag('ul', HTML.literal('').join(items))
def render_people_removable(self, customer, field):
people = customer.people
if not people:
return ""
route_prefix = self.get_route_prefix()
permission_prefix = self.get_permission_prefix()
view_url = lambda p, i: self.request.route_url('people.view', uuid=p.uuid)
actions = [
grids.GridAction('view', icon='zoomin', url=view_url),
]
if self.people_detachable and self.request.has_perm('{}.detach_person'.format(permission_prefix)):
url = lambda p, i: self.request.route_url('{}.detach_person'.format(route_prefix),
uuid=customer.uuid, person_uuid=p.uuid)
actions.append(
grids.GridAction('detach', icon='trash', url=url))
columns = ['first_name', 'last_name', 'display_name']
g = grids.Grid(
key='{}.people'.format(route_prefix),
data=customer.people,
columns=columns,
labels={'display_name': "Full Name"},
url=lambda p: self.request.route_url('people.view', uuid=p.uuid),
linked_columns=columns,
main_actions=actions)
return HTML.literal(g.render_grid())
def render_groups(self, customer, field):
groups = customer.groups
if not groups:
return ""
items = []
for group in groups:
text = "({}) {}".format(group.id, group.name)
url = self.request.route_url('customergroups.view', uuid=group.uuid)
items.append(HTML.tag('li', tags.link_to(text, url)))
return HTML.tag('ul', HTML.literal('').join(items))
# def configure_mobile_fieldset(self, fs): # def configure_mobile_fieldset(self, fs):
# fs.configure( # fs.configure(
# include=[ # include=[
@ -241,6 +301,40 @@ class CustomersView(MasterView):
(model.CustomerPerson, 'customer_uuid'), (model.CustomerPerson, 'customer_uuid'),
] ]
def detach_person(self):
customer = self.get_instance()
person = self.Session.query(model.Person).get(self.request.matchdict['person_uuid'])
if not person:
return self.notfound()
if person in customer.people:
customer.people.remove(person)
else:
self.request.session.flash("No change; person \"{}\" not attached to customer \"{}\"".format(
person, customer))
return self.redirect(self.request.get_referrer())
@classmethod
def defaults(cls, config):
route_prefix = cls.get_route_prefix()
url_prefix = cls.get_url_prefix()
permission_prefix = cls.get_permission_prefix()
model_key = cls.get_model_key()
model_title = cls.get_model_title()
cls._defaults(config)
# detach person
if cls.people_detachable:
config.add_tailbone_permission(permission_prefix, '{}.detach_person'.format(permission_prefix),
"Detach a Person from a {}".format(model_title))
config.add_route('{}.detach_person'.format(route_prefix), '{}/{{{}}}/detach-person/{{person_uuid}}'.format(url_prefix, model_key),
# request_method='POST',
)
config.add_view(cls, attr='detach_person', route_name='{}.detach_person'.format(route_prefix),
permission='{}.detach_person'.format(permission_prefix))
# # TODO: this is referenced by some custom apps, but should be moved?? # # TODO: this is referenced by some custom apps, but should be moved??
# def unique_id(value, field): # def unique_id(value, field):