Add some links between employees / people / customers views

This commit is contained in:
Lance Edgar 2016-11-21 17:47:24 -06:00
parent 686bcfc74c
commit fdd0b6ec3b
4 changed files with 72 additions and 50 deletions

View file

@ -35,6 +35,7 @@ from .common import (StrippedTextFieldRenderer, CodeTextAreaFieldRenderer, Autoc
from .files import FileFieldRenderer from .files import FileFieldRenderer
# TODO: deprecate / remove Link renderers
from .people import (PersonFieldRenderer, PersonFieldLinkRenderer, from .people import (PersonFieldRenderer, PersonFieldLinkRenderer,
CustomerFieldRenderer, CustomerFieldLinkRenderer) CustomerFieldRenderer, CustomerFieldLinkRenderer)

View file

@ -26,12 +26,9 @@ People Field Renderers
from __future__ import unicode_literals, absolute_import from __future__ import unicode_literals, absolute_import
from .common import AutocompleteFieldRenderer
from webhelpers.html import tags from webhelpers.html import tags
from tailbone.forms.renderers.common import AutocompleteFieldRenderer
__all__ = ['PersonFieldRenderer', 'PersonFieldLinkRenderer',
'CustomerFieldRenderer', 'CustomerFieldLinkRenderer']
class PersonFieldRenderer(AutocompleteFieldRenderer): class PersonFieldRenderer(AutocompleteFieldRenderer):
@ -41,19 +38,14 @@ class PersonFieldRenderer(AutocompleteFieldRenderer):
service_route = 'people.autocomplete' service_route = 'people.autocomplete'
class PersonFieldLinkRenderer(PersonFieldRenderer):
"""
Renderer for :class:`rattail.db.model.Person` instance fields (with hyperlink).
"""
def render_readonly(self, **kwargs): def render_readonly(self, **kwargs):
person = self.raw_value person = self.raw_value
if person: if not person:
return tags.link_to( return ''
unicode(person), return tags.link_to(person, self.request.route_url('people.view', uuid=person.uuid))
self.request.route_url('people.view', uuid=person.uuid))
return u'' # TODO: deprecate / remove this
PersonFieldLinkRenderer = PersonFieldRenderer
class CustomerFieldRenderer(AutocompleteFieldRenderer): class CustomerFieldRenderer(AutocompleteFieldRenderer):
@ -63,16 +55,11 @@ class CustomerFieldRenderer(AutocompleteFieldRenderer):
service_route = 'customers.autocomplete' service_route = 'customers.autocomplete'
class CustomerFieldLinkRenderer(CustomerFieldRenderer):
"""
Renderer for :class:`rattail.db.model.Customer` instance fields (with hyperlink).
"""
def render_readonly(self, **kwargs): def render_readonly(self, **kwargs):
customer = self.raw_value customer = self.raw_value
if customer: if not customer:
return tags.link_to( return ''
unicode(customer), return tags.link_to(customer, self.request.route_url('customers.view', uuid=customer.uuid))
self.request.route_url('customers.view', uuid=customer.uuid))
return u'' # TODO: deprecate / remove this
CustomerFieldLinkRenderer = CustomerFieldRenderer

View file

@ -28,10 +28,9 @@ from __future__ import unicode_literals, absolute_import
import sqlalchemy as sa import sqlalchemy as sa
from rattail import enum
from rattail.db import model from rattail.db import model
import formalchemy import formalchemy as fa
from tailbone import forms from tailbone import forms
from tailbone.db import Session from tailbone.db import Session
@ -67,8 +66,8 @@ class EmployeesView(MasterView):
g.filters['id'].label = "ID" g.filters['id'].label = "ID"
g.filters['status'].default_active = True g.filters['status'].default_active = True
g.filters['status'].default_verb = 'equal' g.filters['status'].default_verb = 'equal'
g.filters['status'].default_value = enum.EMPLOYEE_STATUS_CURRENT g.filters['status'].default_value = self.enum.EMPLOYEE_STATUS_CURRENT
g.filters['status'].set_value_renderer(EnumValueRenderer(enum.EMPLOYEE_STATUS)) g.filters['status'].set_value_renderer(EnumValueRenderer(self.enum.EMPLOYEE_STATUS))
else: else:
del g.filters['id'] del g.filters['id']
del g.filters['status'] del g.filters['status']
@ -97,7 +96,7 @@ class EmployeesView(MasterView):
g.last_name, g.last_name,
g.phone.label("Phone Number"), g.phone.label("Phone Number"),
g.email.label("Email Address"), g.email.label("Email Address"),
g.status.with_renderer(forms.EnumFieldRenderer(enum.EMPLOYEE_STATUS)), g.status.with_renderer(forms.renderers.EnumFieldRenderer(self.enum.EMPLOYEE_STATUS)),
], ],
readonly=True) readonly=True)
@ -108,38 +107,47 @@ class EmployeesView(MasterView):
def query(self, session): def query(self, session):
q = session.query(model.Employee).join(model.Person) q = session.query(model.Employee).join(model.Person)
if not self.request.has_perm('employees.edit'): if not self.request.has_perm('employees.edit'):
q = q.filter(model.Employee.status == enum.EMPLOYEE_STATUS_CURRENT) q = q.filter(model.Employee.status == self.enum.EMPLOYEE_STATUS_CURRENT)
return q return q
def configure_fieldset(self, fs): def _preconfigure_fieldset(self, fs):
fs.append(forms.AssociationProxyField('first_name')) fs.append(forms.AssociationProxyField('first_name'))
fs.append(forms.AssociationProxyField('last_name')) fs.append(forms.AssociationProxyField('last_name'))
fs.append(forms.AssociationProxyField('display_name'))
fs.append(StoresField('stores')) fs.append(StoresField('stores'))
fs.append(DepartmentsField('departments')) fs.append(DepartmentsField('departments'))
fs.person.set(renderer=forms.renderers.PersonFieldRenderer)
fs.display_name.set(label="Short Name")
fs.phone.set(label="Phone Number", readonly=True)
fs.email.set(label="Email Address", readonly=True)
fs.status.set(renderer=forms.renderers.EnumFieldRenderer(self.enum.EMPLOYEE_STATUS))
fs.id.set(label="ID")
def configure_fieldset(self, fs):
fs.configure( fs.configure(
include=[ include=[
fs.id.label("ID"), fs.person,
fs.first_name, fs.first_name,
fs.last_name, fs.last_name,
fs.display_name, fs.display_name,
fs.phone.label("Phone Number").readonly(), fs.phone,
fs.email.label("Email Address").readonly(), fs.email,
fs.status.with_renderer(forms.EnumFieldRenderer(enum.EMPLOYEE_STATUS)), fs.status,
fs.id,
fs.stores, fs.stores,
fs.departments, fs.departments,
]) ])
class StoresField(formalchemy.Field): class StoresField(fa.Field):
def __init__(self, name, **kwargs): def __init__(self, name, **kwargs):
kwargs.setdefault('type', formalchemy.types.Set) kwargs.setdefault('type', fa.types.Set)
kwargs.setdefault('options', Session.query(model.Store).order_by(model.Store.name)) kwargs.setdefault('options', Session.query(model.Store).order_by(model.Store.name))
kwargs.setdefault('value', self.get_value) kwargs.setdefault('value', self.get_value)
kwargs.setdefault('multiple', True) kwargs.setdefault('multiple', True)
kwargs.setdefault('size', 3) kwargs.setdefault('size', 3)
formalchemy.Field.__init__(self, name=name, **kwargs) fa.Field.__init__(self, name=name, **kwargs)
def get_value(self, employee): def get_value(self, employee):
return [s.uuid for s in employee.stores] return [s.uuid for s in employee.stores]
@ -159,15 +167,15 @@ class StoresField(formalchemy.Field):
employee.stores.remove(store) employee.stores.remove(store)
class DepartmentsField(formalchemy.Field): class DepartmentsField(fa.Field):
def __init__(self, name, **kwargs): def __init__(self, name, **kwargs):
kwargs.setdefault('type', formalchemy.types.Set) kwargs.setdefault('type', fa.types.Set)
kwargs.setdefault('options', Session.query(model.Department).order_by(model.Department.name)) kwargs.setdefault('options', Session.query(model.Department).order_by(model.Department.name))
kwargs.setdefault('value', self.get_value) kwargs.setdefault('value', self.get_value)
kwargs.setdefault('multiple', True) kwargs.setdefault('multiple', True)
kwargs.setdefault('size', 10) kwargs.setdefault('size', 10)
formalchemy.Field.__init__(self, name=name, **kwargs) fa.Field.__init__(self, name=name, **kwargs)
def get_value(self, employee): def get_value(self, employee):
return [d.uuid for d in employee.departments] return [d.uuid for d in employee.departments]
@ -197,7 +205,7 @@ class EmployeesAutocomplete(AutocompleteView):
def filter_query(self, q): def filter_query(self, q):
return q.join(model.Employee)\ return q.join(model.Employee)\
.filter(model.Employee.status == enum.EMPLOYEE_STATUS_CURRENT) .filter(model.Employee.status == self.enum.EMPLOYEE_STATUS_CURRENT)
def value(self, person): def value(self, person):
return person.employee.uuid return person.employee.uuid

View file

@ -2,7 +2,7 @@
################################################################################ ################################################################################
# #
# Rattail -- Retail Software Framework # Rattail -- Retail Software Framework
# Copyright © 2010-2015 Lance Edgar # Copyright © 2010-2016 Lance Edgar
# #
# This file is part of Rattail. # This file is part of Rattail.
# #
@ -28,13 +28,31 @@ from __future__ import unicode_literals, absolute_import
import sqlalchemy as sa import sqlalchemy as sa
import formalchemy as fa
from pyramid.httpexceptions import HTTPFound, HTTPNotFound from pyramid.httpexceptions import HTTPFound, HTTPNotFound
from webhelpers.html import HTML, tags
from tailbone.views import MasterView, AutocompleteView from tailbone.views import MasterView, AutocompleteView
from rattail.db import model from rattail.db import model
class CustomersFieldRenderer(fa.FieldRenderer):
def render_readonly(self, **kwargs):
customers = self.raw_value
if not customers:
return ''
items = []
for customer in customers:
customer = customer.customer
items.append(HTML.tag('li', c=tags.link_to('{} {}'.format(customer.id, customer),
self.request.route_url('customers.view', uuid=customer.uuid))))
return HTML.tag('ul', c=items)
class PeopleView(MasterView): class PeopleView(MasterView):
""" """
Master view for the Person class. Master view for the Person class.
@ -89,16 +107,24 @@ class PeopleView(MasterView):
return instance.person return instance.person
raise HTTPNotFound raise HTTPNotFound
def _preconfigure_fieldset(self, fs):
fs.display_name.set(label="Full Name")
fs.phone.set(label="Phone Number", readonly=True)
fs.email.set(label="Email Address", readonly=True)
fs.address.set(label="Mailing Address", readonly=True)
fs._customers.set(renderer=CustomersFieldRenderer, readonly=True)
def configure_fieldset(self, fs): def configure_fieldset(self, fs):
fs.configure( fs.configure(
include=[ include=[
fs.display_name.label("Full Name"), fs.display_name,
fs.first_name, fs.first_name,
fs.middle_name, fs.middle_name,
fs.last_name, fs.last_name,
fs.phone.label("Phone Number").readonly(), fs.phone,
fs.email.label("Email Address").readonly(), fs.email,
fs.address.label("Mailing Address").readonly(), fs.address,
fs._customers,
]) ])