Changeset 12478 for main/kofacustom.wdu


Ignore:
Timestamp:
15 Jan 2015, 22:12:25 (10 years ago)
Author:
Henrik Bettermann
Message:

Integrate WebPay? (school fees only).

Location:
main/kofacustom.wdu/trunk/src/kofacustom/wdu
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • main/kofacustom.wdu/trunk/src/kofacustom/wdu/interfaces.py

    r11940 r12478  
    3232    # Base fees, do not remove.
    3333
    34     school_fee_base = schema.Float(
    35         title = _(u'School Fee (ignored)'),
    36         default = 0.0,
    37         required = False,
    38         )
    39 
    4034    application_fee = schema.Float(
    4135        title = _(u'Application Fee (fallback)'),
     
    7064    # Additional fees in custom package add here
    7165
     66    school_fee_fresh = schema.Float(
     67        title = _(u'School Fees Fresh Students'),
     68        description = _('tution fee + other charges + tech fees + gateway fee'),
     69        default = 0.0,
     70        required = False,
     71        )
     72
     73    school_fee_returning = schema.Float(
     74        title = _(u'School Fees Returning Students'),
     75        description = _('tution fee + other charges + tech fees + gateway fee'),
     76        default = 0.0,
     77        required = False,
     78        )
    7279
    7380    def getSessionString():
  • main/kofacustom.wdu/trunk/src/kofacustom/wdu/interswitch/browser.py

    r11940 r12478  
    1717##
    1818import httplib
     19import hashlib
    1920import grok
     21from waeup.kofa.interfaces import CLEARED
    2022from kofacustom.nigeria.interswitch.browser import (
    2123    InterswitchPaymentRequestWebservicePageApplicant,
     
    2729from kofacustom.wdu.interfaces import MessageFactory as _
    2830
    29 PRODUCT_ID = '57'
    30 SITE_NAME = 'wdu-kofa.waeup.org'
    31 PROVIDER_ACCT = '00000000'
    32 PROVIDER_BANK_ID = '00'
     31PRODUCT_ID = '6207'
     32SITE_NAME = 'wdu.waeup.org'
     33PROVIDER_ACCT = '0137712635'
     34PROVIDER_BANK_ID = '10'
    3335PROVIDER_ITEM_NAME = 'BT Education'
    34 INSTITUTION_NAME = 'Skeleton'
     36INSTITUTION_NAME = 'WDU'
    3537CURRENCY = '566'
    36 GATEWAY_AMT = 150.0
    37 #QUERY_URL = 'https://webpay.interswitchng.com/paydirect/services/TransactionQueryURL.aspx'
    38 #QUERY_URL = 'https://testwebpay.interswitchng.com/test_paydirect/services/TransactionQueryURL.aspx'
    39 POST_ACTION = 'https://webpay.interswitchng.com/paydirect/webpay/pay.aspx'
    40 #POST_ACTION = 'https://testwebpay.interswitchng.com/test_paydirect/webpay/pay.aspx'
     38GATEWAY_AMT = 300.0
    4139
    42 HOST = 'webpay.interswitchng.com'
    43 #HOST = 'testwebpay.interswitchng.com'
    44 URL = '/paydirect/services/TransactionQueryWs.asmx'
    45 #URL = '/test_paydirect/services/TransactionQueryWs.asmx'
    46 httplib.HTTPConnection.debuglevel = 0
     40POST_ACTION = 'https://stageserv.interswitchng.com/test_paydirect/pay'
     41#POST_ACTION = 'https://webpay.interswitchng.com/paydirect/pay'
     42
     43#HOST = 'webpay.interswitchng.com'
     44HOST = 'stageserv.interswitchng.com'
     45HTTPS = True
     46
     47#URL = '/paydirect/services/TransactionQueryWs.asmx'
     48URL = '/test_paydirect/services/TransactionQueryWS.asmx'
     49
     50httplib.HTTPSConnection.debuglevel = 0
    4751
    4852class CustomInterswitchPageStudent(InterswitchPageStudent):
     
    5559    currency = CURRENCY
    5660    product_id = PRODUCT_ID
     61    mac = 'CEF793CBBE838AA0CBB29B74D571113B4EA6586D3BA77E7CFA0B95E278364EFC4526ED7BD255A366CDDE11F1F607F0F844B09D93B16F7CFE87563B2272007AB3'
    5762
    5863    def update(self):
     
    6974        xmldict['provider_bank_id'] = PROVIDER_BANK_ID
    7075        xmldict['provider_item_name'] = PROVIDER_ITEM_NAME
    71         # Institution data
    72         xmldict['institution_acct'] = '00000000'
    73         xmldict['institution_bank_id'] = '00'
    74         xmldict['institution_amt'] = '0.0'
    75         provider_amt = 0.0
    76         self.pay_item_id = '0000'
     76        xmldict['institution_acct_1'] = '4742014159'
     77        xmldict['institution_bank_id_1'] = '47'
     78        xmldict['institution_amt_1'] = '0.0'
     79        xmldict['institution_acct_2'] = '0029688237'
     80        xmldict['institution_bank_id_2'] = '11'
     81        xmldict['institution_amt_2'] = '0.0'
     82        provider_amt = 4000.0
     83        self.pay_item_id = '101'
     84        # other charges + tech fee
     85        if self.context.student.state == CLEARED:
     86            institution_amt_2 = 207500.0 + 1000.0
     87        else :
     88            institution_amt_2 = 150500.0 + 1000.0
    7789        xmldict['provider_amt'] = 100 * provider_amt
    7890        xmldict['institution_item_name'] = self.category
    7991        xmldict['institution_name'] = INSTITUTION_NAME
    80         xmldict['institution_amt'] = 100 * (
    81             self.context.amount_auth - provider_amt - GATEWAY_AMT)
     92        xmldict['institution_amt_1'] = 100 * (
     93            self.context.amount_auth - provider_amt - GATEWAY_AMT - institution_amt_2)
     94        xmldict['institution_amt_2'] = 100 * institution_amt_2
     95
    8296        # Interswitch amount is not part of the xml data
    83         if provider_amt == 0:
    84             xmltext = """<payment_item_detail>
     97        xmltext = """<payment_item_detail>
    8598<item_details detail_ref="%(detail_ref)s" college="%(institution_name)s" department="%(department)s" faculty="%(faculty)s">
    86 <item_detail item_id="1" item_name="%(institution_item_name)s" item_amt="%(institution_amt)d" bank_id="%(institution_bank_id)s" acct_num="%(institution_acct)s" />
    87 </item_details>
    88 </payment_item_detail>""" % xmldict
    89         else:
    90             xmltext = """<payment_item_detail>
    91 <item_details detail_ref="%(detail_ref)s" college="%(institution_name)s" department="%(department)s" faculty="%(faculty)s">
    92 <item_detail item_id="1" item_name="%(institution_item_name)s" item_amt="%(institution_amt)d" bank_id="%(institution_bank_id)s" acct_num="%(institution_acct)s" />
    93 <item_detail item_id="2" item_name="%(provider_item_name)s" item_amt="%(provider_amt)d" bank_id="%(provider_bank_id)s" acct_num="%(provider_acct)s" />
     99<item_detail item_id="1" item_name="%(institution_item_name)s" item_amt="%(institution_amt_1)d" bank_id="%(institution_bank_id_1)s" acct_num="%(institution_acct_1)s" />
     100<item_detail item_id="2" item_name="other charges and tech fee" item_amt="%(institution_amt_2)d" bank_id="%(institution_bank_id_2)s" acct_num="%(institution_acct_2)s" />
     101<item_detail item_id="3" item_name="%(provider_item_name)s" item_amt="%(provider_amt)d" bank_id="%(provider_bank_id)s" acct_num="%(provider_acct)s" />
    94102</item_details>
    95103</payment_item_detail>""" % xmldict
     
    97105        self.context.provider_amt = provider_amt
    98106        self.context.gateway_amt = GATEWAY_AMT
     107
     108        hashargs = (
     109            self.context.p_id +
     110            PRODUCT_ID +
     111            self.pay_item_id +
     112            str(int(self.amount_auth)) +
     113            self.site_redirect_url +
     114            self.mac)
     115        self.hashvalue = hashlib.sha512(hashargs).hexdigest()
    99116        return
    100117
    101 class CustomInterswitchPageApplicant(InterswitchPageApplicant):
    102     """ View which sends a POST request to the Interswitch
    103     CollegePAY payment gateway.
    104     """
    105     grok.context(ICustomApplicantOnlinePayment)
    106     action = POST_ACTION
    107     site_name = SITE_NAME
    108     currency = CURRENCY
    109     pay_item_id = '0000'
    110     product_id = PRODUCT_ID
    111 
    112     def update(self):
    113         super(CustomInterswitchPageApplicant, self).update()
    114         xmldict = {}
    115         provider_amt = 400.0
    116         xmldict['institution_acct'] = '00000000000'
    117         xmldict['institution_bank_id'] = '00'
    118         xmldict['detail_ref'] = self.context.p_id
    119         xmldict['provider_amt'] = 100 * provider_amt
    120         xmldict['provider_acct'] = PROVIDER_ACCT
    121         xmldict['provider_bank_id'] = PROVIDER_BANK_ID
    122         xmldict['provider_item_name'] = PROVIDER_ITEM_NAME
    123         xmldict['institution_amt'] = 100 * (self.context.amount_auth - provider_amt - GATEWAY_AMT)
    124         xmldict['institution_item_name'] = self.context.p_category
    125         xmldict['institution_name'] = INSTITUTION_NAME
    126         # Interswitch amount is not part of the xml data
    127         xmltext = """<payment_item_detail>
    128 <item_details detail_ref="%(detail_ref)s" college="%(institution_name)s">
    129 <item_detail item_id="1" item_name="%(institution_item_name)s" item_amt="%(institution_amt)d" bank_id="%(institution_bank_id)s" acct_num="%(institution_acct)s" />
    130 <item_detail item_id="2" item_name="%(provider_item_name)s" item_amt="%(provider_amt)d" bank_id="%(provider_bank_id)s" acct_num="%(provider_acct)s" />
    131 </item_details>
    132 </payment_item_detail>""" % xmldict
    133         self.xml_data = """<input type="hidden" name="xml_data" value='%s'  />""" % xmltext
    134         self.context.provider_amt = provider_amt
    135         self.context.gateway_amt = GATEWAY_AMT
    136         return
    137118
    138119class CustomInterswitchPaymentRequestWebservicePageStudent(
     
    144125    gateway_host = HOST
    145126    gateway_url = URL
     127    https = HTTPS
    146128
    147129class CustomInterswitchPaymentRequestWebservicePageApplicant(
     
    153135    gateway_host = HOST
    154136    gateway_url = URL
     137    https = HTTPS
  • main/kofacustom.wdu/trunk/src/kofacustom/wdu/interswitch/tests.py

    r11940 r12478  
    5252
    5353    def test_interswitch_form(self):
     54        self.app['configuration']['2004'].school_fee_fresh = 442800.0
     55        self.app['configuration']['2004'].school_fee_returning = 385800.0
    5456        # Manager can access InterswitchForm
    5557        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
     
    6870                           self.browser.contents)
    6971        self.assertMatches(
    70             '...<span>40000.0</span>...',
     72            '...<span>442800.0</span>...',
    7173            self.browser.contents)
    7274        self.payment_url = self.browser.url
    7375        self.browser.getLink("CollegePAY", index=0).click()
    74         # The total amount to be processed by Interswitch
    75         # has been reduced by the Interswitch fee of 150 Nairas
    76         self.assertMatches('...<input type="hidden" name="pay_item_id" value="0000" />...',
     76        self.assertMatches('...<input type="hidden" name="pay_item_id" value="101" />...',
    7777                           self.browser.contents)
    7878        self.assertMatches('...Total Amount Authorized:...',
     
    8080        self.assertEqual(self.student.current_mode, 'ug_ft')
    8181        self.assertMatches(
    82             '...<input type="hidden" name="amount" value="4000000" />...',
    83             self.browser.contents)
    84         self.assertMatches(
    85             '...item_name="School Fee" item_amt="4000000" bank_id="00" acct_num="00000000"...',
     82            '...<input type="hidden" name="amount" value="44280000" />...',
     83            self.browser.contents)
     84        self.assertMatches(
     85            '...item_name="School Fees" item_amt="23000000" bank_id="47" acct_num="4742014159"...',
    8686            self.browser.contents)
    8787
  • main/kofacustom.wdu/trunk/src/kofacustom/wdu/students/utils.py

    r11966 r12478  
    3030    # refix
    3131    STUDENT_ID_PREFIX = u'D'
     32
     33    def setPaymentDetails(self, category, student,
     34            previous_session, previous_level):
     35        """Create Payment object and set the payment data of a student for
     36        the payment category specified.
     37
     38        """
     39        p_item = u''
     40        amount = 0.0
     41        if previous_session:
     42            if previous_session < student['studycourse'].entry_session:
     43                return _('The previous session must not fall below '
     44                         'your entry session.'), None
     45            if category == 'schoolfee':
     46                # School fee is always paid for the following session
     47                if previous_session > student['studycourse'].current_session:
     48                    return _('This is not a previous session.'), None
     49            else:
     50                if previous_session > student['studycourse'].current_session - 1:
     51                    return _('This is not a previous session.'), None
     52            p_session = previous_session
     53            p_level = previous_level
     54            p_current = False
     55        else:
     56            p_session = student['studycourse'].current_session
     57            p_level = student['studycourse'].current_level
     58            p_current = True
     59        academic_session = self._getSessionConfiguration(p_session)
     60        if academic_session == None:
     61            return _(u'Session configuration object is not available.'), None
     62        # Determine fee.
     63        if category == 'schoolfee':
     64            try:
     65                certificate = student['studycourse'].certificate
     66                p_item = certificate.code
     67            except (AttributeError, TypeError):
     68                return _('Study course data are incomplete.'), None
     69            if previous_session:
     70                # Students can pay for previous sessions in all
     71                # workflow states.  Fresh students are excluded by the
     72                # update method of the PreviousPaymentAddFormPage.
     73                if previous_level == 100:
     74                    amount = getattr(
     75                        academic_session, 'school_fee_fresh', 0.0)
     76                else:
     77                    amount = getattr(
     78                        academic_session, 'school_fee_returning', 0.0)
     79            else:
     80                if student.state == CLEARED:
     81                    amount = getattr(
     82                        academic_session, 'school_fee_fresh', 0.0)
     83                elif student.state == RETURNING:
     84                    # In case of returning school fee payment the
     85                    # payment session and level contain the values of
     86                    # the session the student has paid for. Payment
     87                    # session is always next session.
     88                    p_session, p_level = self.getReturningData(student)
     89                    academic_session = self._getSessionConfiguration(p_session)
     90                    if academic_session == None:
     91                        return _(
     92                            u'Session configuration object is not available.'
     93                            ), None
     94                    amount = getattr(
     95                        academic_session, 'school_fee_returning', 0.0)
     96                elif student.is_postgrad and student.state == PAID:
     97                    # Returning postgraduate students also pay for the
     98                    # next session but their level always remains the
     99                    # same.
     100                    p_session += 1
     101                    academic_session = self._getSessionConfiguration(p_session)
     102                    if academic_session == None:
     103                        return _(
     104                            u'Session configuration object is not available.'
     105                            ), None
     106                    amount = 0.0 # not yet configured
     107        elif category == 'clearance':
     108            try:
     109                p_item = student['studycourse'].certificate.code
     110            except (AttributeError, TypeError):
     111                return _('Study course data are incomplete.'), None
     112            amount = academic_session.clearance_fee
     113        elif category == 'bed_allocation':
     114            p_item = self.getAccommodationDetails(student)['bt']
     115            amount = academic_session.booking_fee
     116        elif category == 'hostel_maintenance':
     117            amount = 0.0
     118            bedticket = student['accommodation'].get(
     119                str(student.current_session), None)
     120            if bedticket:
     121                p_item = bedticket.bed_coordinates
     122                if bedticket.bed.__parent__.maint_fee > 0:
     123                    amount = bedticket.bed.__parent__.maint_fee
     124                else:
     125                    # fallback
     126                    amount = academic_session.maint_fee
     127            else:
     128                # Should not happen because this is already checked
     129                # in the browser module, but anyway ...
     130                portal_language = getUtility(IKofaUtils).PORTAL_LANGUAGE
     131                p_item = trans(_('no bed allocated'), portal_language)
     132        elif category == 'transcript':
     133            amount = academic_session.transcript_fee
     134        if amount in (0.0, None):
     135            return _('Amount could not be determined.'), None
     136        if self.samePaymentMade(student, category, p_item, p_session):
     137            return _('This type of payment has already been made.'), None
     138        if self._isPaymentDisabled(p_session, category, student):
     139            return _('Payment temporarily disabled.'), None
     140        payment = createObject(u'waeup.StudentOnlinePayment')
     141        timestamp = ("%d" % int(time()*10000))[1:]
     142        payment.p_id = "p%s" % timestamp
     143        payment.p_category = category
     144        payment.p_item = p_item
     145        payment.p_session = p_session
     146        payment.p_level = p_level
     147        payment.p_current = p_current
     148        payment.amount_auth = amount
     149        return None, payment
  • main/kofacustom.wdu/trunk/src/kofacustom/wdu/utils/utils.py

    r10765 r12478  
    1818"""Customize general helper utilities for Kofa.
    1919"""
     20from copy import deepcopy
    2021from kofacustom.nigeria.utils.utils import NigeriaKofaUtils
    2122
     
    2425    """
    2526
     27    PAYMENT_CATEGORIES = {
     28        'schoolfee': 'School Fees',
     29        #'clearance': 'Acceptance Fee',
     30        #'bed_allocation': 'Bed Allocation Fee',
     31        #'hostel_maintenance': 'Hostel Maintenance Fee',
     32        #'transfer': 'Transfer Fee',
     33        #'gown': 'Gown Hire Fee',
     34        'application': 'Application Fee',
     35        #'transcript': 'Transcript Fee',
     36        }
     37
     38    SELECTABLE_PAYMENT_CATEGORIES = deepcopy(PAYMENT_CATEGORIES)
     39
     40    PREVIOUS_PAYMENT_CATEGORIES = deepcopy(SELECTABLE_PAYMENT_CATEGORIES)
Note: See TracChangeset for help on using the changeset viewer.