Ignore:
Timestamp:
20 May 2012, 05:46:07 (12 years ago)
Author:
Henrik Bettermann
Message:

Add new workflow transitions for postgraduate students. Take care for correct payment. Since pg students bypass course registration, we need new names and titles for session activation button and page.

Location:
main/waeup.kofa/trunk/src/waeup/kofa
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.kofa/trunk/src/waeup/kofa/students/browser.py

    r8434 r8471  
    16861686        return
    16871687
    1688 class StartCourseRegistrationPage(KofaPage):
     1688class StartSessionPage(KofaPage):
    16891689    grok.context(IStudentStudyCourse)
    1690     grok.name('start_course_registration')
     1690    grok.name('start_session')
    16911691    grok.require('waeup.handleStudent')
    16921692    grok.template('enterpin')
    1693     label = _('Start course registration')
     1693    label = _('Start session')
    16941694    ac_prefix = 'SFE'
    16951695    notice = ''
    16961696    pnav = 4
    1697     buttonname = _('Start course registration now')
     1697    buttonname = _('Start now')
    16981698
    16991699    def update(self, SUBMIT=None):
    1700         if not self.context.getStudent().state in (CLEARED,RETURNING):
    1701             self.flash(_("You are in wrong state."))
    1702             self.redirect(self.url(self.context))
    1703             return
    1704         if not self.context.may_register:
    1705             self.flash(_("You are not entitled to start course registration."))
     1700        if not self.context.next_session_allowed:
     1701            self.flash(_("You are not entitled to start session."))
    17061702            self.redirect(self.url(self.context))
    17071703            return
     
    17171713            return
    17181714        # Mark pin as used (this also fires a pin related transition)
    1719         # and fire transition start_clearance
    17201715        if code.state == USED:
    17211716            self.flash(_('Activation code has already been used.'))
     
    17241719            comment = _(u"invalidated")
    17251720            # Here we know that the ac is in state initialized so we do not
    1726             # expect an exception, but the owner might be different
     1721            # expect an error, but the owner might be different
    17271722            if not invalidate_accesscode(
    17281723                pin,comment,self.context.getStudent().student_id):
     
    17351730            IWorkflowInfo(self.context.getStudent()).fireTransition(
    17361731                'pay_school_fee')
    1737         self.flash(_('Course registration has been started.'))
     1732        elif self.context.getStudent().state == PAID:
     1733            IWorkflowInfo(self.context.getStudent()).fireTransition(
     1734                'pay_pg_fee')
     1735        self.flash(_('Session started.'))
    17381736        self.redirect(self.url(self.context))
    17391737        return
  • main/waeup.kofa/trunk/src/waeup/kofa/students/studycourse.py

    r8337 r8471  
    2727    IStudentStudyCourse, IStudentNavigation, IStudentStudyLevel)
    2828from waeup.kofa.students.studylevel import CourseTicket
     29from waeup.kofa.students.workflow import CLEARED, RETURNING, PAID
    2930from waeup.kofa.utils.helpers import attrs_to_fields
    3031
     
    4344
    4445    @property
    45     def may_register(self):
    46         return True
     46    def next_session_allowed(self):
     47        if self.getStudent().state in (CLEARED, RETURNING):
     48            return True
     49        if self.getStudent().state == PAID \
     50            and self.getStudent().current_mode.startswith('pg'):
     51            return True
     52        return False
    4753
    4854    def addStudentStudyLevel(self, cert, studylevel):
  • main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_browser.py

    r8468 r8471  
    14831483        self.assertTrue('Successfully removed' in self.browser.contents)
    14841484
    1485         # The new SFE-0 pin can be used for starting course registration
     1485        # The new SFE-0 pin can be used for starting new session
    14861486        self.browser.open(self.studycourse_path)
    1487         self.browser.getLink('Start course registration').click()
     1487        self.browser.getLink('Start session').click()
    14881488        pin = self.app['accesscodes']['SFE-0'].keys()[0]
    14891489        parts = pin.split('-')[1:]
     
    14911491        self.browser.getControl(name="ac_series").value = sfeseries
    14921492        self.browser.getControl(name="ac_number").value = sfenumber
    1493         self.browser.getControl("Start course registration now").click()
    1494         self.assertMatches('...Course registration has been started...',
     1493        self.browser.getControl("Start now").click()
     1494        self.assertMatches('...Session started...',
    14951495                           self.browser.contents)
    14961496        self.assertTrue(self.student.state == 'school fee paid')
     1497        return
     1498
     1499    def test_postgraduate_payments(self):
     1500        self.certificate.study_mode = 'pg_ft'
     1501        self.certificate.start_level = 999
     1502        self.certificate.end_level = 999
     1503        self.student['studycourse'].current_level = 999
     1504        # Login
     1505        self.browser.open(self.login_path)
     1506        self.browser.getControl(name="form.login").value = self.student_id
     1507        self.browser.getControl(name="form.password").value = 'spwd'
     1508        self.browser.getControl("Login").click()
     1509        # Students can add online school fee payment tickets.
     1510        IWorkflowState(self.student).setState('cleared')
     1511        self.browser.open(self.payments_path)
     1512        self.browser.getControl("Add online payment ticket").click()
     1513        self.browser.getControl(name="form.p_category").value = ['schoolfee']
     1514        self.browser.getControl("Create ticket").click()
     1515        self.assertMatches('...ticket created...',
     1516                           self.browser.contents)
     1517        ctrl = self.browser.getControl(name='val_id')
     1518        value = ctrl.options[0]
     1519        self.browser.getLink(value).click()
     1520        self.assertMatches('...Amount Authorized...',
     1521                           self.browser.contents)
     1522        # Payment session and level are current ones.
     1523        # Postgrads have to school_fee_1.
     1524        self.assertEqual(self.student['payments'][value].amount_auth, 40000.0)
     1525        self.assertEqual(self.student['payments'][value].p_session, 2004)
     1526        self.assertEqual(self.student['payments'][value].p_level, 999)
     1527
     1528        # We simulate the approval
     1529        self.assertEqual(len(self.app['accesscodes']['SFE-0']),0)
     1530        self.browser.open(self.browser.url + '/fake_approve')
     1531        self.assertMatches('...Successful payment...',
     1532                          self.browser.contents)
     1533
     1534        # The new SFE-0 pin can be used for starting session
     1535        self.browser.open(self.studycourse_path)
     1536        self.browser.getLink('Start session').click()
     1537        pin = self.app['accesscodes']['SFE-0'].keys()[0]
     1538        parts = pin.split('-')[1:]
     1539        sfeseries, sfenumber = parts
     1540        self.browser.getControl(name="ac_series").value = sfeseries
     1541        self.browser.getControl(name="ac_number").value = sfenumber
     1542        self.browser.getControl("Start now").click()
     1543        self.assertMatches('...Session started...',
     1544                           self.browser.contents)
     1545        self.assertTrue(self.student.state == 'school fee paid')
     1546
     1547        # Postgrad students do not need to register courses the
     1548        # can just pay for the next session.
     1549        self.browser.open(self.payments_path)
     1550        # Remove first payment to be sure that we access the right ticket
     1551        del self.student['payments'][value]
     1552        self.browser.getControl("Add online payment ticket").click()
     1553        self.browser.getControl(name="form.p_category").value = ['schoolfee']
     1554        self.browser.getControl("Create ticket").click()
     1555        ctrl = self.browser.getControl(name='val_id')
     1556        value = ctrl.options[0]
     1557        self.browser.getLink(value).click()
     1558        # Payment session has increased by one, payment level remains the same.
     1559        # Returning Postgraduates have to pay school_fee_2.
     1560        self.assertEqual(self.student['payments'][value].amount_auth, 20000.0)
     1561        self.assertEqual(self.student['payments'][value].p_session, 2005)
     1562        self.assertEqual(self.student['payments'][value].p_level, 999)
     1563
     1564        # Student is still in old session
     1565        self.assertEqual(self.student.current_session, 2004)
     1566
     1567        # We do not need to pay the ticket if any other
     1568        # SFE pin is provided
     1569        pin_container = self.app['accesscodes']
     1570        pin_container.createBatch(
     1571            datetime.utcnow(), 'some_userid', 'SFE', 9.99, 1)
     1572        pin = pin_container['SFE-1'].values()[0].representation
     1573        sfeseries, sfenumber = pin.split('-')[1:]
     1574        # The new SFE-1 pin can be used for starting new session
     1575        self.browser.open(self.studycourse_path)
     1576        self.browser.getLink('Start session').click()
     1577        self.browser.getControl(name="ac_series").value = sfeseries
     1578        self.browser.getControl(name="ac_number").value = sfenumber
     1579        self.browser.getControl("Start now").click()
     1580        self.assertMatches('...Session started...',
     1581                           self.browser.contents)
     1582        self.assertTrue(self.student.state == 'school fee paid')
     1583        # Student is in new session
     1584        self.assertEqual(self.student.current_session, 2005)
     1585        self.assertEqual(self.student['studycourse'].current_level, 999)
    14971586        return
    14981587
  • main/waeup.kofa/trunk/src/waeup/kofa/students/utils.py

    r8420 r8471  
    3636from zope.formlib.form import setUpEditWidgets
    3737
    38 from waeup.kofa.interfaces import IExtFileStore, IKofaUtils, RETURNING
     38from waeup.kofa.interfaces import IExtFileStore, IKofaUtils, RETURNING, PAID
    3939from waeup.kofa.interfaces import MessageFactory as _
    4040from waeup.kofa.students.interfaces import IStudentsUtils
     
    278278                details['p_session'], details[
    279279                    'p_level'] = self.getReturningData(student)
     280            elif student.current_mode.startswith('pg') and student.state == PAID:
     281                # Returning postgraduate students also pay for the next session
     282                # but their level always remains the same.
     283                details['p_session'] += 1
     284                details['amount'] = getattr(
     285                    student['studycourse'].certificate,'school_fee_2')
    280286        elif category == 'clearance':
    281287            details['p_item'] = student['studycourse'].certificate.code
  • main/waeup.kofa/trunk/src/waeup/kofa/students/viewlets.py

    r8467 r8471  
    431431        return self.view.url(self.view.context, self.target)
    432432
    433 class CourseRegistrationStartActionButton(ManageActionButton):
     433class SartSessionActionButton(ManageActionButton):
    434434    grok.order(1)
    435435    grok.context(IStudentStudyCourse)
     
    437437    grok.require('waeup.handleStudent')
    438438    icon = 'actionicon_start.gif'
    439     text = _('Start course registration')
    440     target = 'start_course_registration'
    441 
    442     @property
    443     def target_url(self):
    444         if not self.context.getStudent().state in (CLEARED,RETURNING) \
    445             or not self.context.may_register:
    446             return ''
    447         return self.view.url(self.view.context, self.target)
     439    text = _('Start session')
     440    target = 'start_session'
     441
     442    @property
     443    def target_url(self):
     444        if self.context.next_session_allowed:
     445            return self.view.url(self.view.context, self.target)
     446        return False
    448447
    449448class AddStudyLevelActionButton(AddActionButton):
  • main/waeup.kofa/trunk/src/waeup/kofa/students/vocabularies.py

    r8098 r8471  
    4040        start_level = int(studycourse.certificate.start_level)
    4141        end_level = int(studycourse.certificate.end_level)
    42         if start_level == 10:
     42        if start_level == 999 or end_level == 999:
     43            levels = [999]
     44        elif start_level == 10:
    4345            levels = [10,] + [level for level in range(100,end_level+200,10)
    4446                if level % 100 < 30]
     
    7375            start_level = 100
    7476            end_level = 1000
     77        if start_level == 999 or end_level == 999:
     78            if value != 999:
     79                return _('Error: wrong level id ${value}',
     80                    mapping={'value': value})
     81            return course_levels.by_value[999].title
    7582        if value < start_level or value > end_level + 120:
    7683            return _('Error: level id ${value} out of range',
  • main/waeup.kofa/trunk/src/waeup/kofa/students/workflow.py

    r8434 r8471  
    106106        transition_id = 'pay_school_fee',
    107107        title = _('Pay school fee'),
    108         msg = _('School fee paid'),
     108        msg = _('Payment made'),
    109109        source = RETURNING,
     110        destination = PAID),
     111
     112    Transition(
     113        transition_id = 'pay_pg_fee',
     114        title = _('Pay postgraduate school fee'),
     115        msg = _('Payment made'),
     116        source = PAID,
    110117        destination = PAID),
    111118
     
    115122        msg = _('School fee payment approved'),
    116123        source = RETURNING,
     124        destination = PAID),
     125
     126    Transition(
     127        transition_id = 'approve_pg_fee',
     128        title = _('Approve postgraduate payment'),
     129        msg = _('School fee payment approved'),
     130        source = PAID,
    117131        destination = PAID),
    118132
     
    198212
    199213    Lock and unlock clearance form.
     214    Triger actions after school fee payment.
    200215    """
    201216
     
    212227        'pay_school_fee', 'approve_school_fee'):
    213228        getUtility(IStudentsUtils).setReturningData(obj)
     229    elif event.transition.transition_id in (
     230        'pay_pg_fee', 'approve_pg_fee'):
     231        new_session = obj['studycourse'].current_session + 1
     232        obj['studycourse'].current_session = new_session
    214233    # In some tests we don't have a students container
    215234    try:
  • main/waeup.kofa/trunk/src/waeup/kofa/university/vocabularies.py

    r8439 r8471  
    3737    (_('800 (Year 8)'),800),
    3838    (_('900 (Year 9)'),900),
     39    (_('Postgraduate Level'),999),
    3940    )
    4041
Note: See TracChangeset for help on using the changeset viewer.