Changeset 17866


Ignore:
Timestamp:
1 Aug 2024, 11:02:51 (7 weeks ago)
Author:
Henrik Bettermann
Message:

Implement final clearance.

Location:
main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/students
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/students/browser.py

    r17811 r17866  
    6565    form_fields[
    6666        'financial_clearance_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
     67    form_fields[
     68        'final_clearance_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
    6769
    6870class NigeriaStudentBaseManageFormPage(StudentBaseManageFormPage):
     
    7173    form_fields = grok.AutoFields(INigeriaStudentBase).omit(
    7274        'student_id', 'adm_code', 'suspended',
    73         'financially_cleared_by', 'financial_clearance_date')
     75        'financially_cleared_by', 'financial_clearance_date',
     76        'finally_cleared_by', 'final_clearance_date')
    7477
    7578class NigeriaStudentBaseEditFormPage(StudentBaseEditFormPage):
     
    400403            note=self.note
    401404            )
     405
     406class ClearStudentFinally(UtilityView, grok.View):
     407    """ Clear student finally by final clearance officer
     408    """
     409    grok.context(INigeriaStudent)
     410    grok.name('clear_finally')
     411    grok.require('waeup.clearStudentFinally')
     412
     413    def update(self):
     414        if self.context.finally_cleared_by:
     415            self.flash(_('This student has already been finally cleared.'),
     416                       type="danger")
     417            self.redirect(self.url(self.context))
     418            return
     419        user = get_current_principal()
     420        if user is None:
     421            usertitle = 'system'
     422        else:
     423            usertitle = getattr(user, 'public_name', None)
     424            if not usertitle:
     425                usertitle = user.title
     426        self.context.finally_cleared_by = usertitle
     427        self.context.final_clearance_date = datetime.utcnow()
     428        self.context.writeLogMessage(self,'finally cleared')
     429        history = IObjectHistory(self.context)
     430        history.addMessage('Finally cleared')
     431        self.flash(_('Student has been finally cleared.'))
     432        self.redirect(self.url(self.context))
     433        return
     434
     435    def render(self):
     436        return
     437
     438class WithdrawFinalClearance(UtilityView, grok.View):
     439    """ Withdraw final clearance by final clearance officer
     440    """
     441    grok.context(INigeriaStudent)
     442    grok.name('withdraw_final_clearance')
     443    grok.require('waeup.clearStudentFinally')
     444
     445    def update(self):
     446        if not self.context.finally_cleared_by:
     447            self.flash(_('This student has not yet been finally cleared.'),
     448                       type="danger")
     449            self.redirect(self.url(self.context))
     450            return
     451        self.context.finally_cleared_by = None
     452        self.context.final_clearance_date = None
     453        self.context.writeLogMessage(self,'final clearance withdrawn')
     454        history = IObjectHistory(self.context)
     455        history.addMessage('Final clearance withdrawn')
     456        self.flash(_('Final clearance withdrawn.'))
     457        self.redirect(self.url(self.context))
     458        return
     459
     460    def render(self):
     461        return
     462
     463cleared_note = """
     464<br /><br /><br />
     465<strong>Finally cleared on %s by %s.</strong>
     466
     467"""
  • main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/students/interfaces.py

    r15469 r17866  
    6767        )
    6868
     69    finally_cleared_by = schema.TextLine(
     70        title = _(u'Finally Cleared by'),
     71        default = None,
     72        required = False,
     73        )
     74
     75    final_clearance_date = schema.Datetime(
     76        title = _(u'Final Clearance Date'),
     77        required = False,
     78        readonly = False,
     79        )
     80
    6981    provisionally_cleared = schema.Bool(
    7082        title = _(u'Provisionally Cleared'),
  • main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/students/permissions.py

    r13856 r17866  
    3838    grok.title(u'Financial Clearance Officer')
    3939    grok.permissions('waeup.clearStudentFinancially')
     40
     41class ClearStudentFinally(grok.Permission):
     42    """The ClearStudentFinally permission is needed to clear students
     43    finally or to reject final clearance. This permission is
     44    meant for final clearance officers.
     45    """
     46    grok.name('waeup.clearStudentFinally')
     47
     48
     49class FinalClearanceOfficer(grok.Role):
     50    """Final Clearance Officers are also allowed to clear
     51    students finally. Usually this role is assigned together
     52    with the BursaryOfficer role and the StudentsOfficer role.
     53    """
     54    grok.name('waeup.FinalClearanceOfficer')
     55    grok.title(u'Final Clearance Officer')
     56    grok.permissions('waeup.clearStudentFinally')
  • main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/students/tests/test_browser.py

    r17611 r17866  
    456456        return
    457457
     458    def test_final_clearance(self):
     459        self.app['users'].addUser('mrbursary', SECRET)
     460        self.app['users']['mrbursary'].email = 'mrbursary@foo.ng'
     461        self.app['users']['mrbursary'].title = u'Carl Pitter'
     462        # Clearance officers needs to get
     463        # the StudentsOfficer site role
     464        prmglobal = IPrincipalRoleManager(self.app)
     465        prmglobal.assignRoleToPrincipal('waeup.StudentsOfficer', 'mrbursary')
     466        # Assign BursaryOfficer role
     467        prmglobal.assignRoleToPrincipal('waeup.BursaryOfficer', 'mrbursary')
     468        # and FinalClearanceOfficer role
     469        prmglobal.assignRoleToPrincipal(
     470            'waeup.FinalClearanceOfficer', 'mrbursary')
     471        # Login
     472        self.browser.open(self.login_path)
     473        self.browser.getControl(name="form.login").value = 'mrbursary'
     474        self.browser.getControl(name="form.password").value = SECRET
     475        self.browser.getControl("Login").click()
     476        # BO can see his roles
     477        self.browser.getLink("My Roles").click()
     478        self.assertMatches(
     479            '...<div>Bursary Officer</div>...',
     480            self.browser.contents)
     481        # BO can view student record
     482        self.browser.open(self.student_path)
     483        # BO can see clearance button ...
     484        self.assertTrue(
     485            'Clear student finally' in self.browser.contents)
     486        # ... but not withdraw button
     487        self.assertFalse(
     488            'Withdraw final clearance' in self.browser.contents)
     489        # BO can clear student
     490        self.browser.getLink("Clear student finally").click()
     491        self.assertTrue(
     492            'Student has been finally cleared' in self.browser.contents)
     493        # Name of BO and date have been stored
     494        self.assertEqual(self.student.finally_cleared_by, 'Carl Pitter')
     495        self.assertMatches(
     496            '<YYYY-MM-DD hh:mm:ss>',
     497            self.student.final_clearance_date.strftime(
     498                "%Y-%m-%d %H:%M:%S"))
     499        # BO can't see clearance button ...
     500        self.assertFalse(
     501            'Clear student finally' in self.browser.contents)
     502        # ... but withdraw button and can withdraw clearance
     503        self.browser.getLink("Withdraw final clearance").click()
     504        self.assertTrue(
     505            'Final clearance withdrawn' in self.browser.contents)
     506        # Name of BO and date have been deleted
     507        self.assertEqual(self.student.finally_cleared_by, None)
     508        self.assertEqual(self.student.final_clearance_date, None)
     509        # Clearance is logged
     510        logfile = os.path.join(
     511            self.app['datacenter'].storage, 'logs', 'students.log')
     512        logcontent = open(logfile).read()
     513        self.assertTrue(
     514            'mrbursary - kofacustom.nigeria.students.browser.ClearStudentFinally'
     515            ' - K1000000 - finally cleared' in logcontent)
     516        self.assertTrue(
     517            'mrbursary - kofacustom.nigeria.students.browser.WithdrawFinalClearance'
     518            ' - K1000000 - final clearance withdrawn' in logcontent)
     519        # Clearance is also stored in the history
     520        self.browser.open(self.history_path)
     521        self.assertMatches(
     522            '...2016-01-16 15:50:48 WAT - Finally cleared by Carl Pitter...',
     523            self.browser.contents)
     524        self.assertMatches(
     525            '...2016-01-16 15:50:48 WAT - Final clearance withdrawn by Carl Pitter...',
     526            self.browser.contents)
     527
    458528    def test_provisionally_cleared(self):
    459529        # Students can edit clearance data
  • main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/students/tests/test_export.py

    r17246 r17866  
    7171            'emp2_position,emp2_reason,emp2_start,emp_end,emp_position,'
    7272            'emp_reason,emp_start,employer,employer2,'
     73            'final_clearance_date,finally_cleared_by,'
    7374            'financial_clearance_date,financially_cleared_by,'
    7475            'firstname,flash_notice,former_matric,'
     
    8788            'current_level,current_session\r\nmy adm code,,,,'
    8889            '"[(\'accounts\', \'A\')]",my clr code,1981-02-04#,,,'
    89             'anna@sample.com,,,,,,,,,,,,,Anna,,,,,,"[(\'accounts\', \'A\')]"'
     90            'anna@sample.com,,,,,,,,,,,,,,,Anna,,,,,,"[(\'accounts\', \'A\')]"'
    9091            ',,,,,,,,,,,,,,,,Tester,,,234,M.,NG,,,,,,,,,,'
    9192            '"Studentroad 21\nLagos 123456\n",,+234-123-12345#,,,123,,,,,'
  • main/kofacustom.nigeria/trunk/src/kofacustom/nigeria/students/viewlets.py

    r17813 r17866  
    9393    icon = 'actionicon_pdf.png'
    9494
     95# Final Clearance Officer buttons
     96
     97class StudentFinallyClearActionButton(ManageActionButton):
     98    grok.order(13)
     99    grok.context(INigeriaStudent)
     100    grok.view(NigeriaStudentBaseDisplayFormPage)
     101    grok.require('waeup.clearStudentFinally')
     102    text = _('Clear student finally')
     103    target = 'clear_finally'
     104    icon = 'actionicon_accept.png'
     105
     106    @property
     107    def target_url(self):
     108        if self.context.finally_cleared_by:
     109            return ''
     110        return self.view.url(self.view.context, self.target)
     111
     112class StudentWithdrawFinalClearanceActionButton(ManageActionButton):
     113    grok.order(14)
     114    grok.context(INigeriaStudent)
     115    grok.view(NigeriaStudentBaseDisplayFormPage)
     116    grok.require('waeup.clearStudentFinally')
     117    text = _('Withdraw final clearance')
     118    target = 'withdraw_final_clearance'
     119    icon = 'actionicon_reject.png'
     120
     121    @property
     122    def target_url(self):
     123        if not self.context.finally_cleared_by:
     124            return ''
     125        return self.view.url(self.view.context, self.target)
     126
    95127# Acceptance Letter
    96128
Note: See TracChangeset for help on using the changeset viewer.