Ignore:
Timestamp:
18 Jun 2012, 17:00:00 (13 years ago)
Author:
Henrik Bettermann
Message:

Implement school fee payment by two instalments. Instalment 1 replaces the original school fee payment, instalment 2 is an additional payment which can only be made if instalment 1 has been paid. Furthermore, instalment 1 can only be made if instalment 2 of the previous session has been paid (returning students only).

Location:
main/waeup.aaue/trunk/src/waeup/aaue
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.aaue/trunk/src/waeup/aaue/interfaces.py

    r8712 r8753  
    9797
    9898    school_fee_base = schema.Float(
    99         title = _(u'School Fee (ignored)'),
     99        title = _(u'School Fee Instalments'),
    100100        default = 0.0,
    101101        required = False,
  • main/waeup.aaue/trunk/src/waeup/aaue/payments/interfaces.py

    r8682 r8753  
    1919from zope import schema
    2020from waeup.kofa.payments.interfaces import IPayment
     21from waeup.kofa.interfaces import SimpleKofaVocabulary
    2122from waeup.kofa.interfaces import MessageFactory as _
     23
     24payment_categories = SimpleKofaVocabulary(
     25    (_('School Fee 1st instalment'),'schoolfee_1'),
     26    (_('School Fee 2nd instalment'),'schoolfee_2'),
     27    (_('Clearance'),'clearance'),
     28    (_('Bed Allocation'),'bed_allocation'),
     29    (_('Hostel Maintenance'),'hostel_maintenance'),
     30    (_('Transfer'),'transfer'),
     31    (_('Gown'),'gown'),
     32    (_('Application Fee'), 'application'),
     33    )
    2234
    2335class ICustomOnlinePayment(IPayment):
     
    2537
    2638    """
     39
     40    p_category = schema.Choice(
     41        title = _(u'Payment Category'),
     42        default = u'schoolfee_1',
     43        vocabulary = payment_categories,
     44        required = True,
     45        )
    2746
    2847    ac = schema.TextLine(
     
    7695        readonly = False,
    7796        )
     97
     98ICustomOnlinePayment['p_category'].order = ICustomOnlinePayment[
     99    'p_category'].order
  • main/waeup.aaue/trunk/src/waeup/aaue/students/payments.py

    r8746 r8753  
    2727from waeup.kofa.utils.helpers import attrs_to_fields
    2828from waeup.aaue.students.interfaces import ICustomStudentOnlinePayment
     29from waeup.aaue.payments.interfaces import payment_categories
    2930
    3031class CustomStudentOnlinePayment(StudentOnlinePayment):
     
    4748        return self.__parent__.__parent__
    4849
     50    @property
     51    def category(self):
     52        return payment_categories.getTermByToken(self.p_category).title
     53
    4954CustomStudentOnlinePayment = attrs_to_fields(CustomStudentOnlinePayment)
    5055
  • main/waeup.aaue/trunk/src/waeup/aaue/students/tests/test_browser.py

    r8723 r8753  
    194194        self.browser.getControl("Add online payment ticket").click()
    195195        self.browser.getControl("Create ticket").click()
     196        self.assertMatches('...Wrong state...',
     197                           self.browser.contents)
     198        IWorkflowState(self.student).setState('cleared')
     199        self.browser.open(self.payments_path + '/addop')
     200        self.browser.getControl("Create ticket").click()
    196201        self.assertMatches('...Amount could not be determined...',
    197202                           self.browser.contents)
    198         IWorkflowState(self.student).setState('cleared')
    199         self.browser.open(self.payments_path + '/addop')
     203
     204        self.app['configuration']['2004'].school_fee_base = 6666.0
     205
     206        self.browser.getControl("Add online payment ticket").click()
    200207        self.browser.getControl("Create ticket").click()
    201208        self.assertMatches('...ticket created...',
     
    217224        self.assertMatches('...This type of payment has already been made...',
    218225                           self.browser.contents)
     226        self.browser.open(self.payments_path + '/addop')
     227        # Also the other payments can be made
     228        self.browser.getControl(name="form.p_category").value = ['gown']
     229        self.browser.getControl("Create ticket").click()
     230        self.assertMatches('...ticket created...',
     231                           self.browser.contents)
     232        self.browser.open(self.payments_path + '/addop')
     233        self.browser.getControl(name="form.p_category").value = ['transfer']
     234        self.browser.getControl("Create ticket").click()
     235        self.assertMatches('...ticket created...',
     236                           self.browser.contents)
     237        self.browser.open(self.payments_path + '/addop')
     238        self.browser.getControl(
     239            name="form.p_category").value = ['bed_allocation']
     240        self.browser.getControl("Create ticket").click()
     241        self.assertMatches('...ticket created...',
     242                           self.browser.contents)
     243        self.browser.open(self.payments_path + '/addop')
     244        self.browser.getControl(
     245            name="form.p_category").value = ['hostel_maintenance']
     246        self.browser.getControl("Create ticket").click()
     247        self.assertMatches('...ticket created...',
     248                           self.browser.contents)
     249        self.browser.open(self.payments_path + '/addop')
     250        self.browser.getControl(name="form.p_category").value = ['clearance']
     251        self.browser.getControl("Create ticket").click()
     252        self.assertMatches('...ticket created...',
     253                           self.browser.contents)
    219254        # Remove all payments so that we can add a school fee payment again
    220255        keys = [i for i in self.student['payments'].keys()]
     
    222257            del self.student['payments'][payment]
    223258        self.browser.open(self.payments_path + '/addop')
    224         self.browser.getControl("Create ticket").click()
    225         self.assertMatches('...ticket created...',
    226                            self.browser.contents)
    227         self.browser.open(self.payments_path + '/addop')
    228         self.browser.getControl(name="form.p_category").value = ['gown']
    229         self.browser.getControl("Create ticket").click()
    230         self.assertMatches('...ticket created...',
    231                            self.browser.contents)
    232         self.browser.open(self.payments_path + '/addop')
    233         self.browser.getControl(name="form.p_category").value = ['transfer']
    234         self.browser.getControl("Create ticket").click()
    235         self.assertMatches('...ticket created...',
    236                            self.browser.contents)
    237         self.browser.open(self.payments_path + '/addop')
    238         self.browser.getControl(
    239             name="form.p_category").value = ['bed_allocation']
    240         self.browser.getControl("Create ticket").click()
    241         self.assertMatches('...ticket created...',
    242                            self.browser.contents)
    243         self.browser.open(self.payments_path + '/addop')
    244         self.browser.getControl(
    245             name="form.p_category").value = ['hostel_maintenance']
    246         self.browser.getControl("Create ticket").click()
    247         self.assertMatches('...ticket created...',
    248                            self.browser.contents)
    249         self.browser.open(self.payments_path + '/addop')
    250         self.browser.getControl(name="form.p_category").value = ['clearance']
    251         self.browser.getControl("Create ticket").click()
    252         self.assertMatches('...ticket created...',
    253                            self.browser.contents)
    254         self.browser.open(self.payments_path + '/addop')
    255         self.browser.getControl(name="form.p_category").value = ['schoolfee']
    256         self.browser.getControl("Create ticket").click()
    257         self.assertMatches('...ticket created...',
    258                            self.browser.contents)
    259         # In state returning we can add a new school fee ticket since
    260         # p_session and p_level is different
     259        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
     260        self.browser.getControl("Create ticket").click()
     261        self.assertMatches('...ticket created...',
     262                           self.browser.contents)
     263        # In state returning we can't add a new school fee ticket
     264        # for the next session because the second instalment is missing ...
    261265        IWorkflowState(self.student).setState('returning')
    262266        self.browser.open(self.payments_path + '/addop')
    263         self.browser.getControl(name="form.p_category").value = ['schoolfee']
    264         self.browser.getControl("Create ticket").click()
    265         self.assertMatches('...ticket created...',
    266                            self.browser.contents)
    267         # In state admitted school fee can't be determined
    268         IWorkflowState(self.student).setState('admitted')
    269         self.browser.open(self.payments_path + '/addop')
    270         self.browser.getControl(name="form.p_category").value = ['schoolfee']
    271         self.browser.getControl("Create ticket").click()
    272         self.assertMatches('...Amount could not be determined...',
     267        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
     268        self.browser.getControl("Create ticket").click()
     269        self.assertMatches('...2nd school fee instalment has not yet been paid...',
     270                           self.browser.contents)
     271        self.browser.open(self.payments_path + '/addop')
     272        self.browser.getControl(name="form.p_category").value = ['schoolfee_2']
     273        # ... and the first one has not yet been approved.
     274        self.browser.getControl("Create ticket").click()
     275        self.assertMatches('...1st school fee instalment has not yet been paid...',
     276                           self.browser.contents)
     277        # Ok, then we approve the first instalment ...
     278        ctrl = self.browser.getControl(name='val_id')
     279        p_id = ctrl.options[0]
     280        self.browser.open(self.payments_path + '/' + p_id + '/approve')
     281        # ... add the second instalment ...
     282        self.browser.open(self.payments_path + '/addop')
     283        self.browser.getControl(name="form.p_category").value = ['schoolfee_2']
     284        self.browser.getControl("Create ticket").click()
     285        self.assertMatches('...ticket created...',
     286                           self.browser.contents)
     287        # ... approve the second instalment ...
     288        ctrl = self.browser.getControl(name='val_id')
     289        p_id = ctrl.options[1]
     290        self.browser.open(self.payments_path + '/' + p_id + '/approve')
     291        # ... and finally add the 1st instalment for the next session.
     292        self.browser.open(self.payments_path + '/addop')
     293        self.browser.getControl(name="form.p_category").value = ['schoolfee_1']
     294        self.browser.getControl("Create ticket").click()
     295        self.assertMatches('...ticket created...',
    273296                           self.browser.contents)
    274297
     
    324347        self.app['configuration']['2004'].booking_fee = 150.0
    325348        self.app['configuration']['2004'].maint_fee = 180.0
     349        self.app['configuration']['2004'].clearance_fee = 1234.0
     350        self.app['configuration']['2004'].school_fee_base = 6666.0
    326351        utils = getUtility(IStudentsUtils)
    327352
    328         error, payment = utils.setPaymentDetails('schoolfee',self.student)
     353        error, payment = utils.setPaymentDetails('schoolfee_1',self.student)
    329354        self.assertEqual(payment, None)
    330         self.assertEqual(error, u'Amount could not be determined.')
     355        self.assertEqual(error, u'Wrong state.')
    331356
    332357        IWorkflowState(self.student).setState('cleared')
    333         error, payment = utils.setPaymentDetails('schoolfee',self.student)
    334         self.assertEqual(payment.p_level, 100)
    335         self.assertEqual(payment.p_session, 2004)
    336         self.assertEqual(payment.amount_auth, 40000.0)
     358        error, payment = utils.setPaymentDetails('schoolfee_1',self.student)
     359        self.assertEqual(payment.p_level, 100)
     360        self.assertEqual(payment.p_session, 2004)
     361        self.assertEqual(payment.amount_auth, 6666.0)
    337362        self.assertEqual(payment.p_item, u'CERT1')
    338363        self.assertEqual(error, None)
     
    340365        # Add penalty fee.
    341366        self.app['configuration']['2004'].penalty_ug = 99.0
    342         error, payment = utils.setPaymentDetails('schoolfee',self.student)
    343         self.assertEqual(payment.amount_auth, 40099.0)
     367        error, payment = utils.setPaymentDetails('schoolfee_1',self.student)
     368        self.assertEqual(payment.amount_auth, 6765.0)
    344369
    345370        IWorkflowState(self.student).setState('returning')
    346         error, payment = utils.setPaymentDetails('schoolfee',self.student)
     371        error, payment = utils.setPaymentDetails('schoolfee_1',self.student)
    347372        self.assertEqual(payment.p_level, 200)
    348373        self.assertEqual(payment.p_session, 2005)
    349         self.assertEqual(payment.amount_auth, 20099.0)
     374        self.assertEqual(payment.amount_auth, 6765.0)
    350375        self.assertEqual(payment.p_item, u'CERT1')
    351376        self.assertEqual(error, None)
     
    354379        self.assertEqual(payment.p_level, 100)
    355380        self.assertEqual(payment.p_session, 2004)
    356         self.assertEqual(payment.amount_auth, 34250.0)
     381        self.assertEqual(payment.amount_auth, 1234.0)
    357382        self.assertEqual(payment.p_item, u'CERT1')
    358383        self.assertEqual(error, None)
  • main/waeup.aaue/trunk/src/waeup/aaue/students/utils.py

    r8712 r8753  
    7676            amount = academic_session.maint_fee
    7777        elif category == 'clearance':
    78             try:
    79                 p_item = student['studycourse'].certificate.code
    80             except (AttributeError, TypeError):
    81                 return _('Study course data are incomplete.'), None
    82             if p_item in ('BEDCET', 'BIOEDCET', 'CHMEDCET', 'ISEDCET',
    83                 'MTHEDCET', 'PHYEDCET', 'ITECET', 'AGREDCET', 'HEEDCET'):
    84                 amount = 17250.0
    85             else:
    86                 amount = 34250.0
    87         elif category == 'schoolfee':
     78            amount = academic_session.clearance_fee
     79            p_item = student['studycourse'].certificate.code
     80        elif category == 'schoolfee_1':
    8881            try:
    8982                certificate = student['studycourse'].certificate
     
    9184            except (AttributeError, TypeError):
    9285                return _('Study course data are incomplete.'), None
     86            payment_allowed = False
    9387            if student.state == CLEARED:
    94                 amount = getattr(certificate, 'school_fee_1', 0.0)
     88                payment_allowed = True
     89                amount = academic_session.school_fee_base
    9590            elif student.state == RETURNING:
    96                 # In case of returning school fee payment the payment session
    97                 # and level contain the values of the session the student
    98                 # has paid for.
    9991                p_session, p_level = self.getReturningData(student)
    100                 amount = getattr(certificate, 'school_fee_2', 0.0)
    101             elif student.is_postgrad and student.state == PAID:
    102                 # Returning postgraduate students also pay for the next session
    103                 # but their level always remains the same.
    104                 p_session += 1
    105                 amount = getattr(certificate, 'school_fee_2', 0.0)
     92                initial_instalment_made = False
     93                for key in student['payments'].keys():
     94                    ticket = student['payments'][key]
     95                    if ticket.p_category == 'schoolfee_1':
     96                        initial_instalment_made = True
     97                    if ticket.p_state == 'paid' and\
     98                       ticket.p_category == 'schoolfee_2' and \
     99                       ticket.p_item == p_item and \
     100                       ticket.p_session == p_session-1: #  = current session
     101                       payment_allowed = True
     102                if not initial_instalment_made:
     103                    payment_allowed = True
     104                amount = academic_session.school_fee_base
     105            else:
     106                return _('Wrong state.'), None
     107            if not payment_allowed:
     108                return _('The previous 2nd school fee instalment '
     109                         'has not yet been paid.'), None
     110        elif category == 'schoolfee_2':
     111            try:
     112                certificate = student['studycourse'].certificate
     113                p_item = certificate.code
     114            except (AttributeError, TypeError):
     115                return _('Study course data are incomplete.'), None
     116            payment_allowed = False
     117            for key in student['payments'].keys():
     118                ticket = student['payments'][key]
     119                if ticket.p_state == 'paid' and\
     120                   ticket.p_category == 'schoolfee_1' and \
     121                   ticket.p_item == p_item and \
     122                   ticket.p_session == p_session:
     123                   payment_allowed = True
     124            if not payment_allowed:
     125                return _('The 1st school fee instalment '
     126                         'has not yet been paid.'), None
     127            amount = academic_session.school_fee_base
    106128        if amount in (0.0, None):
    107129            return _(u'Amount could not be determined.'), None
    108130        # Add session specific penalty fee.
    109         if category == 'schoolfee' and student.is_postgrad:
     131        if category == 'schoolfee_1' and student.is_postgrad:
    110132            amount += academic_session.penalty_pg
    111         elif category == 'schoolfee':
     133        elif category == 'schoolfee_1':
    112134            amount += academic_session.penalty_ug
    113135        # Create ticket.
Note: See TracChangeset for help on using the changeset viewer.