diff --git a/tailbone/templates/people/view_profile_buefy.mako b/tailbone/templates/people/view_profile_buefy.mako
index c3017aa0..1108256d 100644
--- a/tailbone/templates/people/view_profile_buefy.mako
+++ b/tailbone/templates/people/view_profile_buefy.mako
@@ -2,7 +2,8 @@
<%inherit file="/master/view.mako" />
<%def name="page_content()">
-
+
+
%def>
<%def name="render_this_page()">
@@ -179,9 +180,207 @@
% endif
%def>
-<%def name="render_this_page_template()">
- ${parent.render_this_page_template()}
+<%def name="render_employee_tab_template()">
+
+%def>
+
+<%def name="render_employee_tab()">
+
+
+
+
+%def>
+
+<%def name="render_profile_info_template()">
%def>
-<%def name="make_this_page_component()">
- ${parent.make_this_page_component()}
+<%def name="render_this_page_template()">
+ ${parent.render_this_page_template()}
+ ${self.render_employee_tab_template()}
+ ${self.render_profile_info_template()}
+%def>
+
+<%def name="set_employee_data()">
+
+%def>
+
+<%def name="declare_employee_tab_vars()">
+
+%def>
+
+<%def name="make_employee_tab_component()">
+ ${self.declare_employee_tab_vars()}
+
+%def>
+
+<%def name="make_profile_info_component()">
%def>
+<%def name="modify_this_page_vars()">
+ ${parent.modify_this_page_vars()}
+
+%def>
+
+<%def name="make_this_page_component()">
+ ${parent.make_this_page_component()}
+ ${self.set_employee_data()}
+ ${self.make_employee_tab_component()}
+ ${self.make_profile_info_component()}
+%def>
+
${parent.body()}
diff --git a/tailbone/views/core.py b/tailbone/views/core.py
index 9b6a5d38..aa662cf9 100644
--- a/tailbone/views/core.py
+++ b/tailbone/views/core.py
@@ -76,6 +76,14 @@ class View(object):
"""
return getattr(self.request, 'rattail_config', None)
+ def get_rattail_app(self):
+ """
+ Returns the Rattail ``AppHandler`` instance, creating it if necessary.
+ """
+ if not hasattr(self, 'rattail_app'):
+ self.rattail_app = self.rattail_config.get_app()
+ return self.rattail_app
+
def forbidden(self):
"""
Convenience method, to raise a HTTP 403 Forbidden exception.
diff --git a/tailbone/views/people.py b/tailbone/views/people.py
index 17f7fb67..969693d7 100644
--- a/tailbone/views/people.py
+++ b/tailbone/views/people.py
@@ -26,6 +26,8 @@ Person Views
from __future__ import unicode_literals, absolute_import
+import datetime
+
import six
import sqlalchemy as sa
from sqlalchemy import orm
@@ -432,6 +434,15 @@ class PeopleView(MasterView):
'view_profile_url': profile_url,
}
+ def get_context_employee(self, employee):
+ """
+ Return a dict of context data for the given employee.
+ """
+ app = self.get_rattail_app()
+ handler = app.get_employment_handler()
+ context = handler.get_context_employee(employee)
+ return context
+
def get_context_employee_history(self, employee):
data = []
if employee:
@@ -443,6 +454,104 @@ class PeopleView(MasterView):
})
return data
+ def ensure_customer(self, person):
+ """
+ Return the `Customer` record for the given person, establishing it
+ first if necessary.
+ """
+ app = self.get_rattail_app()
+ handler = app.get_clientele_handler()
+ customer = handler.ensure_customer(person)
+ return customer
+
+ def profile_start_employee(self):
+ """
+ View which will cause the person to start being an employee.
+ """
+ person = self.get_instance()
+ app = self.get_rattail_app()
+ handler = app.get_employment_handler()
+
+ reason = handler.why_not_begin_employment(person)
+ if reason:
+ return {'error': reason}
+
+ data = self.request.json_body
+ start_date = datetime.datetime.strptime(data['start_date'], '%Y-%m-%d').date()
+ employee = handler.begin_employment(person, start_date,
+ employee_id=data['id'])
+ return self.profile_start_employee_result(employee, start_date)
+
+ def profile_start_employee_result(self, employee, start_date):
+ return {
+ 'success': True,
+ 'employee': self.get_context_employee(employee),
+ 'employee_view_url': self.request.route_url('employees.view', uuid=employee.uuid),
+ 'start_date': six.text_type(start_date),
+ 'employee_history_data': self.get_context_employee_history(employee),
+ }
+
+ def profile_end_employee(self):
+ """
+ View which will cause the person to stop being an employee.
+ """
+ person = self.get_instance()
+ app = self.get_rattail_app()
+ handler = app.get_employment_handler()
+
+ reason = handler.why_not_end_employment(person)
+ if reason:
+ return {'error': reason}
+
+ data = dict(self.request.json_body)
+ end_date = datetime.datetime.strptime(data['end_date'], '%Y-%m-%d').date()
+ employee = handler.get_employee(person)
+ handler.end_employment(employee, end_date,
+ revoke_access=data.get('revoke_access'))
+ return self.profile_end_employee_result(employee, end_date)
+
+ def profile_end_employee_result(self, employee, end_date):
+ return {
+ 'success': True,
+ 'employee': self.get_context_employee(employee),
+ 'employee_view_url': self.request.route_url('employees.view', uuid=employee.uuid),
+ 'end_date': six.text_type(end_date),
+ 'employee_history_data': self.get_context_employee_history(employee),
+ }
+
+ def profile_edit_employee_history(self):
+ """
+ AJAX view for updating an employee history record.
+ """
+ person = self.get_instance()
+ employee = person.employee
+
+ uuid = self.request.json_body['uuid']
+ history = self.Session.query(model.EmployeeHistory).get(uuid)
+ if not history or history not in employee.history:
+ return {'error': "Must specify a valid Employee History record for this Person."}
+
+ # all history records have a start date, so always update that
+ start_date = self.request.json_body['start_date']
+ start_date = datetime.datetime.strptime(start_date, '%Y-%m-%d').date()
+ history.start_date = start_date
+
+ # only update end_date if history already had one
+ if history.end_date:
+ end_date = self.request.json_body['end_date']
+ end_date = datetime.datetime.strptime(end_date, '%Y-%m-%d').date()
+ history.end_date = end_date
+
+ self.Session.flush()
+ current_history = employee.get_current_history()
+
+ return {
+ 'success': True,
+ 'start_date': six.text_type(current_history.start_date),
+ 'end_date': six.text_type(current_history.end_date or ''),
+ 'employee_history_data': self.get_context_employee_history(employee),
+ }
+
def make_note_form(self, mode, person):
schema = NoteSchema().bind(session=self.Session(),
person_uuid=person.uuid)
@@ -545,6 +654,7 @@ class PeopleView(MasterView):
permission_prefix = cls.get_permission_prefix()
route_prefix = cls.get_route_prefix()
url_prefix = cls.get_url_prefix()
+ instance_url_prefix = cls.get_instance_url_prefix()
model_key = cls.get_model_key()
model_title = cls.get_model_title()
@@ -564,6 +674,24 @@ class PeopleView(MasterView):
config.add_view(cls, attr='view_profile', route_name='{}.view_profile'.format(route_prefix),
permission='{}.view_profile'.format(permission_prefix))
+ # profile - start employee
+ config.add_route('{}.profile_start_employee'.format(route_prefix), '{}/profile/start-employee'.format(instance_url_prefix),
+ request_method='POST')
+ config.add_view(cls, attr='profile_start_employee', route_name='{}.profile_start_employee'.format(route_prefix),
+ permission='people_profile.toggle_employee', renderer='json')
+
+ # profile - end employee
+ config.add_route('{}.profile_end_employee'.format(route_prefix), '{}/profile/end-employee'.format(instance_url_prefix),
+ request_method='POST')
+ config.add_view(cls, attr='profile_end_employee', route_name='{}.profile_end_employee'.format(route_prefix),
+ permission='people_profile.toggle_employee', renderer='json')
+
+ # profile - edit employee history
+ config.add_route('{}.profile_edit_employee_history'.format(route_prefix), '{}/profile/edit-employee-history'.format(instance_url_prefix),
+ request_method='POST')
+ config.add_view(cls, attr='profile_edit_employee_history', route_name='{}.profile_edit_employee_history'.format(route_prefix),
+ permission='people_profile.edit_employee_history', renderer='json')
+
# manage notes from profile view
if cls.manage_notes_from_profile_view: