Add 'Stores' and 'Departments' fields to Employee fieldset.
This commit is contained in:
parent
bcf1032156
commit
7edfc98747
|
@ -1,13 +0,0 @@
|
||||||
## -*- coding: utf-8 -*-
|
|
||||||
<%inherit file="/master/view.mako" />
|
|
||||||
|
|
||||||
${parent.body()}
|
|
||||||
|
|
||||||
<h2>Departments</h2>
|
|
||||||
|
|
||||||
% if departments:
|
|
||||||
<p>This employee is assigned to the following departments:</p>
|
|
||||||
${departments.render_grid()|n}
|
|
||||||
% else:
|
|
||||||
<p>This employee is not assigned to any departments.</p>
|
|
||||||
% endif
|
|
|
@ -31,7 +31,10 @@ import sqlalchemy as sa
|
||||||
from rattail import enum
|
from rattail import enum
|
||||||
from rattail.db import model
|
from rattail.db import model
|
||||||
|
|
||||||
|
import formalchemy
|
||||||
|
|
||||||
from tailbone import forms
|
from tailbone import forms
|
||||||
|
from tailbone.db import Session
|
||||||
from tailbone.views import MasterView, AutocompleteView
|
from tailbone.views import MasterView, AutocompleteView
|
||||||
from tailbone.newgrids import AlchemyGrid, GridAction
|
from tailbone.newgrids import AlchemyGrid, GridAction
|
||||||
from tailbone.newgrids.filters import EnumValueRenderer
|
from tailbone.newgrids.filters import EnumValueRenderer
|
||||||
|
@ -112,6 +115,8 @@ class EmployeesView(MasterView):
|
||||||
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(forms.AssociationProxyField('display_name'))
|
||||||
|
fs.append(StoresField('stores'))
|
||||||
|
fs.append(DepartmentsField('departments'))
|
||||||
fs.configure(
|
fs.configure(
|
||||||
include=[
|
include=[
|
||||||
fs.id.label("ID"),
|
fs.id.label("ID"),
|
||||||
|
@ -121,29 +126,65 @@ class EmployeesView(MasterView):
|
||||||
fs.phone.label("Phone Number").readonly(),
|
fs.phone.label("Phone Number").readonly(),
|
||||||
fs.email.label("Email Address").readonly(),
|
fs.email.label("Email Address").readonly(),
|
||||||
fs.status.with_renderer(forms.EnumFieldRenderer(enum.EMPLOYEE_STATUS)),
|
fs.status.with_renderer(forms.EnumFieldRenderer(enum.EMPLOYEE_STATUS)),
|
||||||
|
fs.stores,
|
||||||
|
fs.departments,
|
||||||
])
|
])
|
||||||
|
|
||||||
def template_kwargs_view(self, **kwargs):
|
|
||||||
employee = kwargs['instance']
|
|
||||||
if employee.departments:
|
|
||||||
|
|
||||||
# TODO: This is the second attempt (after role.users) at using a
|
class StoresField(formalchemy.Field):
|
||||||
# new grid outside of the context of a primary master grid. The
|
|
||||||
# API here is really much hairier than I'd like... Looks like we
|
|
||||||
# shouldn't need a key for this one, for instance (no settings
|
|
||||||
# required), but there is plenty of room for improvement here.
|
|
||||||
departments = sorted(employee.departments, key=unicode)
|
|
||||||
departments = AlchemyGrid('employees.departments', self.request, data=departments, model_class=model.Department,
|
|
||||||
main_actions=[
|
|
||||||
GridAction('view', icon='zoomin',
|
|
||||||
url=lambda d: self.request.route_url('departments.view', uuid=d.uuid)),
|
|
||||||
])
|
|
||||||
departments.configure(include=[departments.name], readonly=True)
|
|
||||||
kwargs['departments'] = departments
|
|
||||||
|
|
||||||
else:
|
def __init__(self, name, **kwargs):
|
||||||
kwargs['departments'] = None
|
kwargs.setdefault('type', formalchemy.types.Set)
|
||||||
return kwargs
|
kwargs.setdefault('options', Session.query(model.Store).order_by(model.Store.name))
|
||||||
|
kwargs.setdefault('value', self.get_value)
|
||||||
|
kwargs.setdefault('multiple', True)
|
||||||
|
kwargs.setdefault('size', 3)
|
||||||
|
formalchemy.Field.__init__(self, name=name, **kwargs)
|
||||||
|
|
||||||
|
def get_value(self, employee):
|
||||||
|
return [s.uuid for s in employee.stores]
|
||||||
|
|
||||||
|
def sync(self):
|
||||||
|
if not self.is_readonly():
|
||||||
|
employee = self.parent.model
|
||||||
|
old_stores = set([s.uuid for s in employee.stores])
|
||||||
|
new_stores = set(self._deserialize())
|
||||||
|
for uuid in new_stores:
|
||||||
|
if uuid not in old_stores:
|
||||||
|
employee._stores.append(model.EmployeeStore(store_uuid=uuid))
|
||||||
|
for uuid in old_stores:
|
||||||
|
if uuid not in new_stores:
|
||||||
|
store = Session.query(model.Store).get(uuid)
|
||||||
|
assert store
|
||||||
|
employee.stores.remove(store)
|
||||||
|
|
||||||
|
|
||||||
|
class DepartmentsField(formalchemy.Field):
|
||||||
|
|
||||||
|
def __init__(self, name, **kwargs):
|
||||||
|
kwargs.setdefault('type', formalchemy.types.Set)
|
||||||
|
kwargs.setdefault('options', Session.query(model.Department).order_by(model.Department.name))
|
||||||
|
kwargs.setdefault('value', self.get_value)
|
||||||
|
kwargs.setdefault('multiple', True)
|
||||||
|
kwargs.setdefault('size', 10)
|
||||||
|
formalchemy.Field.__init__(self, name=name, **kwargs)
|
||||||
|
|
||||||
|
def get_value(self, employee):
|
||||||
|
return [d.uuid for d in employee.departments]
|
||||||
|
|
||||||
|
def sync(self):
|
||||||
|
if not self.is_readonly():
|
||||||
|
employee = self.parent.model
|
||||||
|
old_depts = set([d.uuid for d in employee.departments])
|
||||||
|
new_depts = set(self._deserialize())
|
||||||
|
for uuid in new_depts:
|
||||||
|
if uuid not in old_depts:
|
||||||
|
employee._departments.append(model.EmployeeDepartment(department_uuid=uuid))
|
||||||
|
for uuid in old_depts:
|
||||||
|
if uuid not in new_depts:
|
||||||
|
dept = Session.query(model.Department).get(uuid)
|
||||||
|
assert dept
|
||||||
|
employee.departments.remove(dept)
|
||||||
|
|
||||||
|
|
||||||
class EmployeesAutocomplete(AutocompleteView):
|
class EmployeesAutocomplete(AutocompleteView):
|
||||||
|
|
Loading…
Reference in a new issue