Ignore:
Timestamp:
22 Apr 2012, 12:56:07 (13 years ago)
Author:
Henrik Bettermann
Message:

Reorganize payment customizatiom. Tests will follow.

Let also applicants pay via eTranzact. Show transaction code on display view (slip view will follow).

Location:
main/waeup.uniben/trunk/src/waeup/uniben
Files:
9 added
10 edited

Legend:

Unmodified
Added
Removed
  • main/waeup.uniben/trunk/src/waeup/uniben/applicants/browser.py

    r8196 r8247  
    1919"""
    2020import grok
     21from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget
    2122from waeup.kofa.applicants.interfaces import (
    2223    IApplicantRegisterUpdate, IApplicant, IApplicantEdit)
     
    2425    OnlinePaymentCallbackPage, ExportPDFPage,
    2526    ApplicantManageFormPage, ApplicantEditFormPage,
    26     ApplicantRegistrationPage, ApplicantAddFormPage)
     27    ApplicantRegistrationPage, ApplicantAddFormPage,
     28    OnlinePaymentDisplayFormPage, AcceptanceFeePaymentAddPage,
     29    OnlinePaymentBreadcrumb)
    2730from waeup.kofa.applicants.viewlets import RequestCallbackActionButton
    2831from waeup.kofa.applicants.pdf import PDFApplicationSlip
    2932from waeup.uniben.applicants.interfaces import (
    30     IPGApplicant, IUGApplicant, IPGApplicantEdit, IUGApplicantEdit)
     33    IPGApplicant, IUGApplicant, IPGApplicantEdit, IUGApplicantEdit,
     34    ICustomApplicantOnlinePayment)
    3135from waeup.uniben.interfaces import MessageFactory as _
    3236
    33 class CustomRequestCallbackActionButton(RequestCallbackActionButton):
    34     """ Do not display the base package callback button in custom pages.
     37#class RequestCallbackActionButton(RequestCallbackActionButton):
     38#    """ Do not display the base package callback button in custom pages.
     39#    """
     40#    @property
     41#    def target_url(self):
     42#        return ''
     43
     44#class CustomOnlinePaymentCallbackPage(OnlinePaymentCallbackPage):
     45#    """ Neutralize callback simulation view
     46#    """
     47#    def update(self):
     48#        return
     49
     50class CustomOnlinePaymentBreadcrumb(OnlinePaymentBreadcrumb):
     51    """A breadcrumb for payments.
    3552    """
    36     @property
    37     def target_url(self):
    38         return ''
    39 
    40 class CustomOnlinePaymentCallbackPage(OnlinePaymentCallbackPage):
    41     """ Neutralize callback simulation view
    42     """
    43     def update(self):
    44         return
     53    grok.context(ICustomApplicantOnlinePayment)
    4554
    4655class CustomPDFApplicationSlip(PDFApplicationSlip):
     
    107116        form_fields['reg_number'].for_display = True
    108117        return form_fields
     118
     119class CustomOnlinePaymentDisplayFormPage(OnlinePaymentDisplayFormPage):
     120    """ Page to view an online payment ticket
     121    """
     122    grok.context(ICustomApplicantOnlinePayment)
     123    form_fields = grok.AutoFields(ICustomApplicantOnlinePayment)
     124    form_fields[
     125        'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
     126    form_fields[
     127        'payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
     128    grok.template('payment_view')
     129
     130    @property
     131    def transaction_code(self):
     132        tcode = self.context.p_id
     133        return tcode[len(tcode)-8:len(tcode)]
     134
     135class CustomAcceptanceFeePaymentAddPage(AcceptanceFeePaymentAddPage):
     136    """ Page to add an online payment ticket
     137    """
     138    factory = u'waeup.CustomApplicantOnlinePayment'
     139
     140    def _fillCustomFields(self, payment, session_config):
     141        payment.surcharge_1 = session_config.surcharge_1
     142        payment.surcharge_2 = session_config.surcharge_2
     143        payment.surcharge_3 = session_config.surcharge_3
     144        return payment
  • main/waeup.uniben/trunk/src/waeup/uniben/applicants/interfaces.py

    r8196 r8247  
    2424    AppCatCertificateSource, CertificateSource)
    2525from waeup.kofa.schoolgrades import ResultEntryField
    26 from waeup.kofa.interfaces import SimpleKofaVocabulary
     26from waeup.kofa.interfaces import SimpleKofaVocabulary, academic_sessions_vocab
    2727from waeup.kofa.schema import FormattedDate
    2828from waeup.kofa.students.vocabularies import nats_vocab
     
    3030    lgas_vocab, high_qual, high_grade, exam_types)
    3131from waeup.uniben.interfaces import MessageFactory as _
    32 
     32from waeup.uniben.payments.interfaces import ICustomOnlinePayment
    3333
    3434class IUGApplicant(IApplicantBaseData):
     
    261261    respective form page.
    262262    """
     263class ICustomApplicantOnlinePayment(ICustomOnlinePayment):
     264    """An applicant payment via payment gateways.
     265
     266    """
  • main/waeup.uniben/trunk/src/waeup/uniben/applicants/utils.py

    r8101 r8247  
    1919"""
    2020
     21import sys
    2122import grok
     23from hurry.workflow.interfaces import IWorkflowInfo, InvalidTransitionError
    2224from waeup.kofa.applicants.utils import ApplicantsUtils
    2325from waeup.uniben.interfaces import MessageFactory as _
     26
     27
     28def actions_after_applicant_payment(applicant, view):
     29    wf_info = IWorkflowInfo(applicant)
     30    try:
     31        wf_info.fireTransition('pay')
     32    except InvalidTransitionError:
     33        view.flash('Error: %s' % sys.exc_info()[1])
     34        return
    2435
    2536class ApplicantsUtils(ApplicantsUtils):
  • main/waeup.uniben/trunk/src/waeup/uniben/browser/pages.py

    r8204 r8247  
    1919from waeup.kofa.browser.pages import (
    2020    SessionConfigurationAddFormPage, SessionConfigurationManageFormPage)
    21 from waeup.kofa.interfaces import IUserAccount
    2221from waeup.uniben.interfaces import (
    2322    ICustomSessionConfiguration, ICustomSessionConfigurationAdd)
    24 from waeup.kofa.browser.pages import (
    25     UserEditFormPage, UserManageFormPage, AddUserFormPage)
    2623
    2724class CustomSessionConfigurationAddFormPage(SessionConfigurationAddFormPage):
  • main/waeup.uniben/trunk/src/waeup/uniben/etranzact/browser.py

    r8129 r8247  
    2323from waeup.kofa.browser.layout import KofaPage, UtilityView
    2424from waeup.kofa.students.interfaces import IStudentOnlinePayment
    25 from waeup.kofa.students.browser import write_log_message
    26 from waeup.kofa.students.viewlets import RequestCallbackActionButton
     25from waeup.kofa.applicants.interfaces import IApplicantOnlinePayment
     26from waeup.kofa.applicants.viewlets import RequestCallbackActionButton as RCABApplicant
     27from waeup.kofa.students.viewlets import RequestCallbackActionButton as RCABStudent
    2728from waeup.uniben.interfaces import MessageFactory as _
    28 from waeup.uniben.utils.utils import actions_after_payment
     29from waeup.uniben.students.utils import actions_after_student_payment
     30from waeup.uniben.applicants.utils import actions_after_applicant_payment
    2931
    30 TERMINAL_ID = '0000000001'
    31 QUERY_URL =   'http://demo.etranzact.com:8080/WebConnect/queryPayoutletTransaction.jsp'
     32TERMINAL_ID = '0500000003'
     33QUERY_URL =   'https://www.etranzact.net/Query/queryPayoutletTransaction.jsp'
    3234
    33 class EtranzactEnterPinActionButton(RequestCallbackActionButton):
    34     grok.order(5)
     35
     36def query_etranzact(confirmation_number, user, payment, view):
     37    ob_class = view.__implemented__.__name__.replace('waeup.kofa.','')
     38    postdict = {}
     39    postdict['TERMINAL_ID'] = TERMINAL_ID
     40    #postdict['RESPONSE_URL'] = 'http://dummy'
     41    postdict['CONFIRMATION_NO'] = confirmation_number
     42    data = urllib.urlencode(postdict)
     43    try:
     44        f = urllib.urlopen(url=QUERY_URL, data=data)
     45        success = f.read()
     46        user.loggerInfo(ob_class, 'callback received: %s' % success)
     47        if 'COL1' not in success:
     48            view.flash(_('Invalid or unsuccessful callback: ${a}',
     49                mapping = {'a': success}))
     50            user.loggerInfo(ob_class, 'invalid callback: %s' % payment.p_id)
     51            payment.p_state = 'failed'
     52            return False
     53        success = success.replace('%20',' ').split('&')
     54        # We expect at least two parameters
     55        if len(success) < 2:
     56            view.flash(_('Invalid callback: ${a}',
     57                mapping = {'a': success}))
     58            user.loggerInfo(ob_class, 'invalid callback: %s' % payment.p_id)
     59            payment.p_state = 'failed'
     60            return False
     61        try:
     62            success_dict = dict([tuple(i.split('=')) for i in success])
     63        except ValueError:
     64            view.flash(_('Invalid callback: ${a}',
     65                mapping = {'a': success}))
     66            user.loggerInfo(ob_class, 'invalid callback: %s' % payment.p_id)
     67            payment.p_state = 'failed'
     68            return False
     69    except IOError:
     70        view.flash(_('eTranzact IOError'))
     71        return False
     72    payment.r_code = u'ET'
     73    payment.r_desc = u'%s' % success_dict.get('TRANS_DESCR')
     74    payment.r_amount_approved = float(success_dict.get('TRANS_AMOUNT',0.0))
     75    payment.r_card_num = None
     76    payment.r_pay_reference = u'%s' % success_dict.get('RECEIPT_NO')
     77    if payment.r_amount_approved != payment.amount_auth:
     78        view.flash(_('Wrong amount'))
     79        user.loggerInfo(ob_class, 'successful callback but wrong amount: %s'
     80            % payment.p_id)
     81        payment.p_state = 'failed'
     82        return False
     83    tcode = payment.p_id
     84    tcode = tcode[len(tcode)-8:len(tcode)]
     85    col1 = success_dict.get('COL1')
     86    col1 = col1[len(col1)-8:len(col1)]
     87    if tcode != col1:
     88        view.flash(_('Wrong transaction code'))
     89        write_log_message(
     90            view,'successful callback but wrong transaction code: %s'
     91            % payment.p_id)
     92        user.loggerInfo(ob_class, 'successful callback wrong transaction code: %s'
     93            % payment.p_id)
     94        payment.p_state = 'failed'
     95        return False
     96    user.loggerInfo(ob_class, 'successful callback: %s' % payment.p_id)
     97    payment.p_state = 'paid'
     98    payment.payment_date = datetime.now()
     99    return True
     100
     101class EtranzactEnterPinActionButtonApplicant(RCABApplicant):
    35102    icon = 'actionicon_call.png'
    36103    text = _('Query eTranzact History')
    37104    target = 'enterpin'
    38105
    39 class EtranzactEnterPinPage(KofaPage):
     106class EtranzactEnterPinActionButtonStudent(RCABStudent):
     107    icon = 'actionicon_call.png'
     108    text = _('Query eTranzact History')
     109    target = 'enterpin'
     110
     111class EtranzactEnterPinPageStudent(KofaPage):
    40112    """
    41113    """
     
    49121    action = 'query_history'
    50122
    51 class EtranzactQueryHistoryPage(UtilityView, grok.View):
     123class EtranzactEnterPinPageApplicant(EtranzactEnterPinPageStudent):
     124    """
     125    """
     126    grok.require('waeup.payApplicant')
     127    grok.context(IApplicantOnlinePayment)
     128
     129class EtranzactQueryHistoryPageStudent(UtilityView, grok.View):
    52130    """ Query history of eTranzact payments
    53131    """
     
    61139            return
    62140        student = self.context.getStudent()
    63         postdict = {}
    64         postdict['TERMINAL_ID'] = TERMINAL_ID
    65         #postdict['RESPONSE_URL'] = 'http://dummy'
    66         postdict['CONFIRMATION_NO'] = confirmation_number
    67         data = urllib.urlencode(postdict)
    68         try:
    69             f = urllib.urlopen(url=QUERY_URL, data=data)
    70             success = f.read()
    71             if '-1' in success:
    72                 self.flash(_('Unsuccessful callback'))
    73                 write_log_message(self,'unsuccessful callback: %s' % self.context.p_id)
    74                 self.context.p_state = 'failed'
    75                 return
    76             success = success.replace('%20',' ').split('&')
    77             # We expect at least two parameters
    78             if len(success) < 2:
    79                 self.flash(_('Invalid callback: ${a}',
    80                     mapping = {'a': success}))
    81                 write_log_message(self,'invalid callback: %s' % self.context.p_id)
    82                 self.context.p_state = 'failed'
    83                 return
    84             try:
    85                 success_dict = dict([tuple(i.split('=')) for i in success])
    86             except ValueError:
    87                 self.flash(_('Invalid callback: ${a}',
    88                     mapping = {'a': success}))
    89                 write_log_message(self,'invalid callback: %s' % self.context.p_id)
    90                 self.context.p_state = 'failed'
    91                 return
    92         except IOError:
    93             self.flash(_('eTranzact IOError'))
    94             return
    95         write_log_message(self,'callback received: %s' % success)
    96 
    97         self.context.r_code = u'ET'
    98         self.context.r_desc = u'%s' % success_dict.get('TRANS_DESCR')
    99         self.context.r_amount_approved = float(success_dict.get('TRANS_AMOUNT',0.0))
    100         self.context.r_card_num = None
    101         self.context.r_pay_reference = u'%s' % success_dict.get('RECEIPT_NO')
    102        
    103         if self.context.r_amount_approved != self.context.amount_auth:
    104             self.flash(_('Wrong amount'))
    105             write_log_message(
    106                 self,'successful callback but wrong amount: %s'
    107                 % self.context.p_id)
    108             self.context.p_state = 'failed'
    109             return
    110 
    111         if success_dict.get('COL1') != self.context.p_id:
    112             self.flash(_('Wrong transaction id'))
    113             write_log_message(
    114                 self,'successful callback but wrong transaction id: %s'
    115                 % self.context.p_id)
    116             self.context.p_state = 'failed'
    117             return
    118 
    119         write_log_message(self,'successful callback: %s' % self.context.p_id)
    120 
    121         self.context.p_state = 'paid'
    122         self.context.payment_date = datetime.now()
    123 
    124         actions_after_payment(student, self.context, self)
    125 
     141        if query_etranzact(confirmation_number, student, self.context, self):
     142            actions_after_student_payment(student, self.context, self)
    126143        return
    127144
     
    129146        self.redirect(self.url(self.context, '@@index'))
    130147        return
     148
     149class EtranzactQueryHistoryPageApplicant(UtilityView, grok.View):
     150    """ Query history of eTranzact payments
     151    """
     152    grok.context(IApplicantOnlinePayment)
     153    grok.name('query_history')
     154    grok.require('waeup.payApplicant')
     155
     156    def update(self, confirmation_number=None):
     157        if self.context.p_state == 'paid':
     158            self.flash(_('This ticket has already been paid.'))
     159            return
     160        applicant = self.context.__parent__
     161        if query_etranzact(confirmation_number, applicant, self.context, self):
     162            actions_after_applicant_payment(applicant, self)
     163        return
     164
     165    def render(self):
     166        self.redirect(self.url(self.context, '@@index'))
     167        return
  • main/waeup.uniben/trunk/src/waeup/uniben/interswitch/browser.py

    r8020 r8247  
    2626from waeup.kofa.students.browser import write_log_message
    2727from waeup.kofa.students.viewlets import RequestCallbackActionButton
    28 from waeup.uniben.utils.utils import actions_after_payment
     28from waeup.uniben.students.utils import actions_after_student_payment
    2929from waeup.uniben.interfaces import MessageFactory as _
    3030
  • main/waeup.uniben/trunk/src/waeup/uniben/students/browser.py

    r8204 r8247  
    1919from zope.formlib.textwidgets import BytesDisplayWidget
    2020from zope.component import getUtility
     21from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget
    2122from waeup.kofa.interfaces import IExtFileStore
     23from waeup.kofa.browser.layout import action
    2224from waeup.kofa.students.browser import (
    2325    StudentPersonalDisplayFormPage,
     
    2527    StudentClearanceDisplayFormPage, OnlinePaymentCallbackPage,
    2628    ExportPDFClearanceSlipPage, StudentBaseManageFormPage,
    27     StudentBaseEditFormPage, StudentPersonalEditFormPage)
     29    StudentBaseEditFormPage, StudentPersonalEditFormPage,
     30    OnlinePaymentDisplayFormPage, OnlinePaymentAddFormPage,
     31    OnlinePaymentBreadcrumb)
    2832from waeup.kofa.students.viewlets import RequestCallbackActionButton
    2933from waeup.uniben.students.interfaces import (
    3034    ICustomStudentBase, ICustomStudent, ICustomStudentPersonal,
    3135    ICustomUGStudentClearance,ICustomPGStudentClearance,
     36    ICustomStudentOnlinePayment,
    3237    )
    3338from waeup.uniben.interfaces import MessageFactory as _
    3439
    35 class CustomRequestCallbackActionButton(RequestCallbackActionButton):
     40class CustomOnlinePaymentBreadcrumb(OnlinePaymentBreadcrumb):
     41    """A breadcrumb for payments.
     42    """
     43    grok.context(ICustomStudentOnlinePayment)
     44
     45class RequestCallbackActionButton(RequestCallbackActionButton):
    3646    """ Do not display the base package callback button in custom pages.
    3747    """
     
    144154        return False
    145155
     156class CustomOnlinePaymentDisplayFormPage(OnlinePaymentDisplayFormPage):
     157    """ Page to view an online payment ticket
     158    """
     159    grok.context(ICustomStudentOnlinePayment)
     160    form_fields = grok.AutoFields(ICustomStudentOnlinePayment)
     161    form_fields[
     162        'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
     163    form_fields[
     164        'payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
     165    grok.template('payment_view')
     166
     167    @property
     168    def transaction_code(self):
     169        tcode = self.context.p_id
     170        return tcode[len(tcode)-8:len(tcode)]
     171
     172class CustomOnlinePaymentAddFormPage(OnlinePaymentAddFormPage):
     173    """ Page to add an online payment ticket
     174    """
     175    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).select(
     176        'p_category')
     177    factory = u'waeup.CustomStudentOnlinePayment'
     178
     179    def _fillCustomFields(self, payment, pay_details):
     180        payment.surcharge_1 = pay_details['surcharge_1']
     181        payment.surcharge_2 = pay_details['surcharge_2']
     182        payment.surcharge_3 = pay_details['surcharge_3']
     183        return payment
  • main/waeup.uniben/trunk/src/waeup/uniben/students/interfaces.py

    r8204 r8247  
    1818from zope import schema
    1919from waeup.kofa.schema import TextLineChoice
    20 from waeup.kofa.interfaces import SimpleKofaVocabulary
     20from waeup.kofa.interfaces import SimpleKofaVocabulary, academic_sessions_vocab
    2121from waeup.kofa.schema import FormattedDate
    2222from waeup.kofa.schoolgrades import ResultEntryField
     
    3131    lgas_vocab, high_qual, high_grade, exam_types)
    3232from waeup.uniben.interfaces import MessageFactory as _
     33from waeup.uniben.payments.interfaces import ICustomOnlinePayment
    3334
    3435class ICustomStudentBase(IStudentBase):
     
    339340
    340341    """
     342
     343class ICustomStudentOnlinePayment(ICustomOnlinePayment):
     344    """A student payment via payment gateways.
     345
     346    """
  • main/waeup.uniben/trunk/src/waeup/uniben/students/utils.py

    r8204 r8247  
    2020from waeup.kofa.students.utils import StudentsUtils
    2121from waeup.kofa.students.interfaces import IStudentsUtils
     22from waeup.kofa.accesscodes import create_accesscode
    2223from waeup.uniben.interfaces import MessageFactory as _
    2324
     
    4142    else:
    4243        return 0.0
     44
     45def actions_after_student_payment(student, payment, view):
     46    if payment.p_category == 'clearance':
     47        # Create CLR access code
     48        pin, error = create_accesscode('CLR',0,student.student_id)
     49        if error:
     50            view.flash(_('Valid callback received. ${a}',
     51                mapping = {'a':error}))
     52            return
     53        payment.ac = pin
     54    elif payment.p_category == 'schoolfee':
     55        # Create SFE access code
     56        pin, error = create_accesscode('SFE',0,student.student_id)
     57        if error:
     58            view.flash(_('Valid callback received. ${a}',
     59                mapping = {'a':error}))
     60            return
     61        payment.ac = pin
     62    elif payment.p_category == 'bed_allocation':
     63        # Create HOS access code
     64        pin, error = create_accesscode('HOS',0,student.student_id)
     65        if error:
     66            view.flash(_('Valid callback received. ${a}',
     67                mapping = {'a':error}))
     68            return
     69        payment.ac = pin
     70    view.flash(_('Valid callback received.'))
     71    return
    4372
    4473class CustomStudentsUtils(StudentsUtils):
  • main/waeup.uniben/trunk/src/waeup/uniben/utils/utils.py

    r8242 r8247  
    2121import pytz
    2222from waeup.kofa.utils.utils import KofaUtils, sorted_phone_prefixes
    23 from waeup.kofa.accesscodes import create_accesscode
    2423from waeup.uniben.interfaces import MessageFactory as _
    25 
    26 def actions_after_payment(student, payment, view):
    27     if payment.p_category == 'clearance':
    28         # Create CLR access code
    29         pin, error = create_accesscode('CLR',0,student.student_id)
    30         if error:
    31             view.flash(_('Valid callback received. ${a}',
    32                 mapping = {'a':error}))
    33             return
    34         payment.ac = pin
    35     elif payment.p_category == 'schoolfee':
    36         # Create SFE access code
    37         pin, error = create_accesscode('SFE',0,student.student_id)
    38         if error:
    39             view.flash(_('Valid callback received. ${a}',
    40                 mapping = {'a':error}))
    41             return
    42         payment.ac = pin
    43     elif payment.p_category == 'bed_allocation':
    44         # Create HOS access code
    45         pin, error = create_accesscode('HOS',0,student.student_id)
    46         if error:
    47             view.flash(_('Valid callback received. ${a}',
    48                 mapping = {'a':error}))
    49             return
    50         payment.ac = pin
    51     view.flash(_('Valid callback received.'))
    52     return
    5324
    5425INT_PHONE_PREFIXES = [
Note: See TracChangeset for help on using the changeset viewer.