Sick period checker
===================

The sick period checker is event driven code that reports on sick employees, and
creates 'to-do' actions at predefined periods - a checkup call is recommended
after an employee has been sick for one week, for instance, and an absence
report is flagged as required to be sent to the UWV at six weeks.

Firstly let's setup our adapters. Usully the ZCML handles this, but
since we are running unit tests here, our ZCML isn't loaded.

    >>> from plonehrm.absence.tests import MockEmployee, MockMailer

Next we can create an absent employee:

    >>> from datetime import date, timedelta
    >>> from plonehrm.absence.notifications import checkers
    >>> mock_employee = MockEmployee()
    >>> from plonehrm.absence.interfaces import IAbsenceAdapter
    >>> absentemployee = IAbsenceAdapter(mock_employee)
    >>> absentemployee.add_absence("Broke leg", start_date=date(1979, 1, 29))
    <Absence: Broke leg, ...>
    >>> absentemployee.is_absent()
    True

Then we mock out the employee collection, emailing and current date
logic. We need to RESTORE this at the end of the test!!

    >>> old_get_employees_for_checking = checkers.get_employees_for_checking
    >>> checkers.get_employees_for_checking = lambda x: [mock_employee]
    >>> old_email_address_of_local_managers = checkers.email_adresses_of_local_managers
    >>> checkers.email_adresses_of_local_managers = lambda x: dict(worklocation_managers='fred@there', hrm_managers='simon@here')
    >>> old_HRMEmailer = checkers.HRMEmailer
    >>> checkers.HRMEmailer = MockMailer
    >>> old_current_date = checkers.current_date
    >>> checkers.current_date = lambda: date(1979, 1, 29)
    >>> from plonehrm.absence.notifications import events
    >>> events.localize = lambda x,y: y


Now, lets make a shortcut to the checker function and try running it:

    >>> spc = checkers.sick_period_checker
    >>> spc(None, None)

Initially we have no notifications to send, as our employee only got sick today.
If we move their absence back a week, though, we should be able to trigger a
notification (we can also see our mock emailer reporting the details of the
email it was asked to send):

    >>> absentemployee.current_absence().start_date = date(1979, 1, 29) - timedelta(7)
    >>> spc(None, None)
    absenceweek1email <MockEmployee at > Employee sick - 1 week
    <plonehrm.absence.notifications.events.AbsenceWeek1Event object at ...>    

To prevent duplicate notifications each notification is recorded on the employee -
so an identical call shouldn't generate another notification:

    >>> spc(None, None)

Another notification should occur at 5 weeks:

    >>> absentemployee.current_absence().start_date = date(1979, 1, 29) - timedelta(5*7)
    >>> spc(None, None)
    absenceweek6email <MockEmployee at > Problem analysis - 6 weeks
    <plonehrm.absence.notifications.events.AbsenceWeek6Event object at ...>

...and it shouldn't duplicate:

    >>> spc(None, None)

...and another notification at 7 weeks:

    >>> absentemployee.current_absence().start_date = date(1979, 1, 29) - timedelta(7*7)
    >>> spc(None, None)
    absenceweek8email <MockEmployee at > Plan of action - 8 weeks
    <plonehrm.absence.notifications.events.AbsenceWeek8Event object at ...>

...and it shouldn't duplicate (seeing a pattern?):

    >>> spc(None, None)

Finally the 6 weekly periodic reports should occur from week 14 onwards (we'll
also verify the duplicate supression):

    >>> absentemployee.current_absence().start_date = date(1979, 1, 29) - timedelta(14*7)
    >>> spc(None, None)
    absence6weekrepeatemail <MockEmployee at > Update reintegration file. Week: 14
    <plonehrm.absence.notifications.events.Absence6WeekRepeatEvent object at ...>
    >>> spc(None, None) # Duplicate suppression test
    >>> absentemployee.current_absence().start_date = date(1979, 1, 29) - timedelta(20*7)
    >>> spc(None, None)
    absence6weekrepeatemail <MockEmployee at > Update reintegration file. Week: 20
    <plonehrm.absence.notifications.events.Absence6WeekRepeatEvent object at ...>
    >>> spc(None, None) # Duplicate suppression test


When we close our absence, we can create a new one.

    >>> absentemployee.close_absence(date(1979, 1, 30))
    <Absence: Broke leg...>
    >>> checkers.current_date = lambda: date.today()
    >>> absentemployee.add_absence('Sick again')
    <Absence: Sick again...>

Since our notification duplicate suppression flags have been removed
when we closed the previous absence, new notifications will be sent again.

    >>> checkers.current_date = lambda: date.today() + timedelta(7)
    >>> spc(None, None)
    absenceweek1email <MockEmployee at > Employee sick - 1 week
    <plonehrm.absence.notifications.events.AbsenceWeek1Event object at ...>


Restore the mocked out objects to not mess up other tests:

    >>> checkers.get_employees_for_checking = old_get_employees_for_checking
    >>> checkers.email_adresses_of_local_managers = old_email_address_of_local_managers
    >>> checkers.HRMEmailer = old_HRMEmailer
    >>> checkers.current_date = old_current_date
