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 webhelpers2.html import HTML, tags
from tailbone import grids
from tailbone.db import Session
from tailbone.views import MasterView3 as MasterView, AutocompleteView
@ -50,6 +51,7 @@ class CustomersView(MasterView):
model_class = model.Customer
has_versions = True
supports_mobile = True
people_detachable = True
labels = {
'id': "ID",
@ -78,6 +80,7 @@ class CustomersView(MasterView):
'active_in_pos',
'active_in_pos_sticky',
'people',
'groups',
]
def configure_grid(self, g):
@ -151,6 +154,11 @@ class CustomersView(MasterView):
def configure_form(self, f):
super(CustomersView, self).configure_form(f)
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)
if not self.creating and customer.emails:
@ -160,21 +168,33 @@ class CustomersView(MasterView):
if not self.creating and customer.phones:
f.set_default('default_phone', customer.phones[0].number)
f.set_renderer('default_address', self.render_default_address)
f.set_readonly('default_address')
# default_address
if self.creating:
f.remove_field('default_address')
else:
f.set_renderer('default_address', self.render_default_address)
f.set_readonly('default_address')
f.set_enum('email_preference', self.enum.EMAIL_PREFERENCE)
preferences = list(self.enum.EMAIL_PREFERENCE.items())
preferences.insert(0, ('', "(no preference)"))
f.set_widget('email_preference', dfwidget.SelectWidget(values=preferences))
f.set_renderer('people', self.render_people)
f.set_readonly('people')
# 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_readonly('id')
f.set_renderer('people', self.render_people)
f.set_readonly('people')
# groups
if self.creating:
f.remove_field('groups')
else:
f.set_renderer('groups', self.render_groups)
f.set_readonly('groups')
# TODO: something like this should be supported for default_email, default_phone
# def after_edit(self, customer):
@ -226,6 +246,46 @@ class CustomersView(MasterView):
items.append(HTML.tag('li', link))
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):
# fs.configure(
# include=[
@ -241,6 +301,40 @@ class CustomersView(MasterView):
(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??
# def unique_id(value, field):