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 name="render_this_page()"> @@ -179,9 +180,207 @@ % endif -<%def name="render_this_page_template()"> - ${parent.render_this_page_template()} +<%def name="render_employee_tab_template()"> + + + +<%def name="render_employee_tab()"> + + + + + + +<%def name="render_profile_info_template()"> -<%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 name="set_employee_data()"> + + + +<%def name="declare_employee_tab_vars()"> + + + +<%def name="make_employee_tab_component()"> + ${self.declare_employee_tab_vars()} + + + +<%def name="make_profile_info_component()"> +<%def name="modify_this_page_vars()"> + ${parent.modify_this_page_vars()} + + + +<%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()} + + ${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: