Index: /main/waeup.uniben/trunk/src/waeup/uniben/applicants/browser.py
===================================================================
--- /main/waeup.uniben/trunk/src/waeup/uniben/applicants/browser.py	(revision 8246)
+++ /main/waeup.uniben/trunk/src/waeup/uniben/applicants/browser.py	(revision 8247)
@@ -19,4 +19,5 @@
 """
 import grok
+from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget
 from waeup.kofa.applicants.interfaces import (
     IApplicantRegisterUpdate, IApplicant, IApplicantEdit)
@@ -24,23 +25,31 @@
     OnlinePaymentCallbackPage, ExportPDFPage,
     ApplicantManageFormPage, ApplicantEditFormPage,
-    ApplicantRegistrationPage, ApplicantAddFormPage)
+    ApplicantRegistrationPage, ApplicantAddFormPage,
+    OnlinePaymentDisplayFormPage, AcceptanceFeePaymentAddPage,
+    OnlinePaymentBreadcrumb)
 from waeup.kofa.applicants.viewlets import RequestCallbackActionButton
 from waeup.kofa.applicants.pdf import PDFApplicationSlip
 from waeup.uniben.applicants.interfaces import (
-    IPGApplicant, IUGApplicant, IPGApplicantEdit, IUGApplicantEdit)
+    IPGApplicant, IUGApplicant, IPGApplicantEdit, IUGApplicantEdit,
+    ICustomApplicantOnlinePayment)
 from waeup.uniben.interfaces import MessageFactory as _
 
-class CustomRequestCallbackActionButton(RequestCallbackActionButton):
-    """ Do not display the base package callback button in custom pages.
+#class RequestCallbackActionButton(RequestCallbackActionButton):
+#    """ Do not display the base package callback button in custom pages.
+#    """
+#    @property
+#    def target_url(self):
+#        return ''
+
+#class CustomOnlinePaymentCallbackPage(OnlinePaymentCallbackPage):
+#    """ Neutralize callback simulation view
+#    """
+#    def update(self):
+#        return
+
+class CustomOnlinePaymentBreadcrumb(OnlinePaymentBreadcrumb):
+    """A breadcrumb for payments.
     """
-    @property
-    def target_url(self):
-        return ''
-
-class CustomOnlinePaymentCallbackPage(OnlinePaymentCallbackPage):
-    """ Neutralize callback simulation view
-    """
-    def update(self):
-        return
+    grok.context(ICustomApplicantOnlinePayment)
 
 class CustomPDFApplicationSlip(PDFApplicationSlip):
@@ -107,2 +116,29 @@
         form_fields['reg_number'].for_display = True
         return form_fields
+
+class CustomOnlinePaymentDisplayFormPage(OnlinePaymentDisplayFormPage):
+    """ Page to view an online payment ticket
+    """
+    grok.context(ICustomApplicantOnlinePayment)
+    form_fields = grok.AutoFields(ICustomApplicantOnlinePayment)
+    form_fields[
+        'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
+    form_fields[
+        'payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
+    grok.template('payment_view')
+
+    @property
+    def transaction_code(self):
+        tcode = self.context.p_id
+        return tcode[len(tcode)-8:len(tcode)]
+
+class CustomAcceptanceFeePaymentAddPage(AcceptanceFeePaymentAddPage):
+    """ Page to add an online payment ticket
+    """
+    factory = u'waeup.CustomApplicantOnlinePayment'
+
+    def _fillCustomFields(self, payment, session_config):
+        payment.surcharge_1 = session_config.surcharge_1
+        payment.surcharge_2 = session_config.surcharge_2
+        payment.surcharge_3 = session_config.surcharge_3
+        return payment
Index: /main/waeup.uniben/trunk/src/waeup/uniben/applicants/browser_templates/payment_view.pt
===================================================================
--- /main/waeup.uniben/trunk/src/waeup/uniben/applicants/browser_templates/payment_view.pt	(revision 8247)
+++ /main/waeup.uniben/trunk/src/waeup/uniben/applicants/browser_templates/payment_view.pt	(revision 8247)
@@ -0,0 +1,18 @@
+<table class="form-table" i18n:domain="waeup.uniben"
+  tal:define="files provider:files">
+  <tbody>
+    <tal:widgets content="structure provider:widgets" />
+    <tr tal:condition="python: files.replace('\n','')">
+      <td class="separator" colspan=2 i18n:translate="">
+        Uploaded Files
+      </td>
+    </tr>
+    <tal:files content="structure files" />
+    <tr>
+      <td class="fieldname">
+        <span i18n:translate="">Transaction Code</span>:
+      </td>
+      <td tal:content="view/transaction_code">TRANSACTIONCODE</td>
+    </tr>
+  </tbody>
+</table>
Index: /main/waeup.uniben/trunk/src/waeup/uniben/applicants/interfaces.py
===================================================================
--- /main/waeup.uniben/trunk/src/waeup/uniben/applicants/interfaces.py	(revision 8246)
+++ /main/waeup.uniben/trunk/src/waeup/uniben/applicants/interfaces.py	(revision 8247)
@@ -24,5 +24,5 @@
     AppCatCertificateSource, CertificateSource)
 from waeup.kofa.schoolgrades import ResultEntryField
-from waeup.kofa.interfaces import SimpleKofaVocabulary
+from waeup.kofa.interfaces import SimpleKofaVocabulary, academic_sessions_vocab
 from waeup.kofa.schema import FormattedDate
 from waeup.kofa.students.vocabularies import nats_vocab
@@ -30,5 +30,5 @@
     lgas_vocab, high_qual, high_grade, exam_types)
 from waeup.uniben.interfaces import MessageFactory as _
-
+from waeup.uniben.payments.interfaces import ICustomOnlinePayment
 
 class IUGApplicant(IApplicantBaseData):
@@ -261,2 +261,6 @@
     respective form page.
     """
+class ICustomApplicantOnlinePayment(ICustomOnlinePayment):
+    """An applicant payment via payment gateways.
+
+    """
Index: /main/waeup.uniben/trunk/src/waeup/uniben/applicants/payment.py
===================================================================
--- /main/waeup.uniben/trunk/src/waeup/uniben/applicants/payment.py	(revision 8247)
+++ /main/waeup.uniben/trunk/src/waeup/uniben/applicants/payment.py	(revision 8247)
@@ -0,0 +1,53 @@
+## $Id$
+##
+## Copyright (C) 2012 Uli Fouquet & Henrik Bettermann
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+"""
+Acceptance fee payment.
+"""
+import grok
+from zope.component.interfaces import IFactory
+from zope.interface import implementedBy
+from waeup.kofa.payments import OnlinePayment
+from waeup.kofa.utils.helpers import attrs_to_fields
+from waeup.uniben.applicants.interfaces import ICustomApplicantOnlinePayment
+
+class CustomApplicantOnlinePayment(OnlinePayment):
+    """This is an online payment.
+    """
+    grok.implements(ICustomApplicantOnlinePayment)
+    grok.provides(ICustomApplicantOnlinePayment)
+
+    def __init__(self):
+        super(CustomApplicantOnlinePayment, self).__init__()
+        return
+
+CustomApplicantOnlinePayment = attrs_to_fields(CustomApplicantOnlinePayment)
+
+# Applicant online payments must be importable. So we might need a factory.
+class CustomApplicantOnlinePaymentFactory(grok.GlobalUtility):
+    """A factory for applicant online payments.
+    """
+    grok.implements(IFactory)
+    grok.name(u'waeup.CustomApplicantOnlinePayment')
+    title = u"Create a new online payment.",
+    description = u"This factory instantiates new online payment instances."
+
+    def __call__(self, *args, **kw):
+        return CustomApplicantOnlinePayment()
+
+    def getInterfaces(self):
+        return implementedBy(CustomApplicantOnlinePayment)
Index: /main/waeup.uniben/trunk/src/waeup/uniben/applicants/utils.py
===================================================================
--- /main/waeup.uniben/trunk/src/waeup/uniben/applicants/utils.py	(revision 8246)
+++ /main/waeup.uniben/trunk/src/waeup/uniben/applicants/utils.py	(revision 8247)
@@ -19,7 +19,18 @@
 """
 
+import sys
 import grok
+from hurry.workflow.interfaces import IWorkflowInfo, InvalidTransitionError
 from waeup.kofa.applicants.utils import ApplicantsUtils
 from waeup.uniben.interfaces import MessageFactory as _
+
+
+def actions_after_applicant_payment(applicant, view):
+    wf_info = IWorkflowInfo(applicant)
+    try:
+        wf_info.fireTransition('pay')
+    except InvalidTransitionError:
+        view.flash('Error: %s' % sys.exc_info()[1])
+        return
 
 class ApplicantsUtils(ApplicantsUtils):
Index: /main/waeup.uniben/trunk/src/waeup/uniben/browser/pages.py
===================================================================
--- /main/waeup.uniben/trunk/src/waeup/uniben/browser/pages.py	(revision 8246)
+++ /main/waeup.uniben/trunk/src/waeup/uniben/browser/pages.py	(revision 8247)
@@ -19,9 +19,6 @@
 from waeup.kofa.browser.pages import (
     SessionConfigurationAddFormPage, SessionConfigurationManageFormPage)
-from waeup.kofa.interfaces import IUserAccount
 from waeup.uniben.interfaces import (
     ICustomSessionConfiguration, ICustomSessionConfigurationAdd)
-from waeup.kofa.browser.pages import (
-    UserEditFormPage, UserManageFormPage, AddUserFormPage)
 
 class CustomSessionConfigurationAddFormPage(SessionConfigurationAddFormPage):
Index: /main/waeup.uniben/trunk/src/waeup/uniben/etranzact/browser.py
===================================================================
--- /main/waeup.uniben/trunk/src/waeup/uniben/etranzact/browser.py	(revision 8246)
+++ /main/waeup.uniben/trunk/src/waeup/uniben/etranzact/browser.py	(revision 8247)
@@ -23,19 +23,91 @@
 from waeup.kofa.browser.layout import KofaPage, UtilityView
 from waeup.kofa.students.interfaces import IStudentOnlinePayment
-from waeup.kofa.students.browser import write_log_message
-from waeup.kofa.students.viewlets import RequestCallbackActionButton
+from waeup.kofa.applicants.interfaces import IApplicantOnlinePayment
+from waeup.kofa.applicants.viewlets import RequestCallbackActionButton as RCABApplicant
+from waeup.kofa.students.viewlets import RequestCallbackActionButton as RCABStudent
 from waeup.uniben.interfaces import MessageFactory as _
-from waeup.uniben.utils.utils import actions_after_payment
+from waeup.uniben.students.utils import actions_after_student_payment
+from waeup.uniben.applicants.utils import actions_after_applicant_payment
 
-TERMINAL_ID = '0000000001'
-QUERY_URL =   'http://demo.etranzact.com:8080/WebConnect/queryPayoutletTransaction.jsp'
+TERMINAL_ID = '0500000003'
+QUERY_URL =   'https://www.etranzact.net/Query/queryPayoutletTransaction.jsp'
 
-class EtranzactEnterPinActionButton(RequestCallbackActionButton):
-    grok.order(5)
+
+def query_etranzact(confirmation_number, user, payment, view):
+    ob_class = view.__implemented__.__name__.replace('waeup.kofa.','')
+    postdict = {}
+    postdict['TERMINAL_ID'] = TERMINAL_ID
+    #postdict['RESPONSE_URL'] = 'http://dummy'
+    postdict['CONFIRMATION_NO'] = confirmation_number
+    data = urllib.urlencode(postdict)
+    try:
+        f = urllib.urlopen(url=QUERY_URL, data=data)
+        success = f.read()
+        user.loggerInfo(ob_class, 'callback received: %s' % success)
+        if 'COL1' not in success:
+            view.flash(_('Invalid or unsuccessful callback: ${a}',
+                mapping = {'a': success}))
+            user.loggerInfo(ob_class, 'invalid callback: %s' % payment.p_id)
+            payment.p_state = 'failed'
+            return False
+        success = success.replace('%20',' ').split('&')
+        # We expect at least two parameters
+        if len(success) < 2:
+            view.flash(_('Invalid callback: ${a}',
+                mapping = {'a': success}))
+            user.loggerInfo(ob_class, 'invalid callback: %s' % payment.p_id)
+            payment.p_state = 'failed'
+            return False
+        try:
+            success_dict = dict([tuple(i.split('=')) for i in success])
+        except ValueError:
+            view.flash(_('Invalid callback: ${a}',
+                mapping = {'a': success}))
+            user.loggerInfo(ob_class, 'invalid callback: %s' % payment.p_id)
+            payment.p_state = 'failed'
+            return False
+    except IOError:
+        view.flash(_('eTranzact IOError'))
+        return False
+    payment.r_code = u'ET'
+    payment.r_desc = u'%s' % success_dict.get('TRANS_DESCR')
+    payment.r_amount_approved = float(success_dict.get('TRANS_AMOUNT',0.0))
+    payment.r_card_num = None
+    payment.r_pay_reference = u'%s' % success_dict.get('RECEIPT_NO')
+    if payment.r_amount_approved != payment.amount_auth:
+        view.flash(_('Wrong amount'))
+        user.loggerInfo(ob_class, 'successful callback but wrong amount: %s'
+            % payment.p_id)
+        payment.p_state = 'failed'
+        return False
+    tcode = payment.p_id
+    tcode = tcode[len(tcode)-8:len(tcode)]
+    col1 = success_dict.get('COL1')
+    col1 = col1[len(col1)-8:len(col1)]
+    if tcode != col1:
+        view.flash(_('Wrong transaction code'))
+        write_log_message(
+            view,'successful callback but wrong transaction code: %s'
+            % payment.p_id)
+        user.loggerInfo(ob_class, 'successful callback wrong transaction code: %s'
+            % payment.p_id)
+        payment.p_state = 'failed'
+        return False
+    user.loggerInfo(ob_class, 'successful callback: %s' % payment.p_id)
+    payment.p_state = 'paid'
+    payment.payment_date = datetime.now()
+    return True
+
+class EtranzactEnterPinActionButtonApplicant(RCABApplicant):
     icon = 'actionicon_call.png'
     text = _('Query eTranzact History')
     target = 'enterpin'
 
-class EtranzactEnterPinPage(KofaPage):
+class EtranzactEnterPinActionButtonStudent(RCABStudent):
+    icon = 'actionicon_call.png'
+    text = _('Query eTranzact History')
+    target = 'enterpin'
+
+class EtranzactEnterPinPageStudent(KofaPage):
     """
     """
@@ -49,5 +121,11 @@
     action = 'query_history'
 
-class EtranzactQueryHistoryPage(UtilityView, grok.View):
+class EtranzactEnterPinPageApplicant(EtranzactEnterPinPageStudent):
+    """
+    """
+    grok.require('waeup.payApplicant')
+    grok.context(IApplicantOnlinePayment)
+
+class EtranzactQueryHistoryPageStudent(UtilityView, grok.View):
     """ Query history of eTranzact payments
     """
@@ -61,67 +139,6 @@
             return
         student = self.context.getStudent()
-        postdict = {}
-        postdict['TERMINAL_ID'] = TERMINAL_ID
-        #postdict['RESPONSE_URL'] = 'http://dummy'
-        postdict['CONFIRMATION_NO'] = confirmation_number
-        data = urllib.urlencode(postdict)
-        try:
-            f = urllib.urlopen(url=QUERY_URL, data=data)
-            success = f.read()
-            if '-1' in success:
-                self.flash(_('Unsuccessful callback'))
-                write_log_message(self,'unsuccessful callback: %s' % self.context.p_id)
-                self.context.p_state = 'failed'
-                return
-            success = success.replace('%20',' ').split('&')
-            # We expect at least two parameters
-            if len(success) < 2:
-                self.flash(_('Invalid callback: ${a}',
-                    mapping = {'a': success}))
-                write_log_message(self,'invalid callback: %s' % self.context.p_id)
-                self.context.p_state = 'failed'
-                return
-            try:
-                success_dict = dict([tuple(i.split('=')) for i in success])
-            except ValueError:
-                self.flash(_('Invalid callback: ${a}',
-                    mapping = {'a': success}))
-                write_log_message(self,'invalid callback: %s' % self.context.p_id)
-                self.context.p_state = 'failed'
-                return
-        except IOError:
-            self.flash(_('eTranzact IOError'))
-            return
-        write_log_message(self,'callback received: %s' % success)
-
-        self.context.r_code = u'ET'
-        self.context.r_desc = u'%s' % success_dict.get('TRANS_DESCR')
-        self.context.r_amount_approved = float(success_dict.get('TRANS_AMOUNT',0.0))
-        self.context.r_card_num = None
-        self.context.r_pay_reference = u'%s' % success_dict.get('RECEIPT_NO')
-        
-        if self.context.r_amount_approved != self.context.amount_auth:
-            self.flash(_('Wrong amount'))
-            write_log_message(
-                self,'successful callback but wrong amount: %s'
-                % self.context.p_id)
-            self.context.p_state = 'failed'
-            return
-
-        if success_dict.get('COL1') != self.context.p_id:
-            self.flash(_('Wrong transaction id'))
-            write_log_message(
-                self,'successful callback but wrong transaction id: %s'
-                % self.context.p_id)
-            self.context.p_state = 'failed'
-            return
-
-        write_log_message(self,'successful callback: %s' % self.context.p_id)
-
-        self.context.p_state = 'paid'
-        self.context.payment_date = datetime.now()
-
-        actions_after_payment(student, self.context, self)
-
+        if query_etranzact(confirmation_number, student, self.context, self):
+            actions_after_student_payment(student, self.context, self)
         return
 
@@ -129,2 +146,22 @@
         self.redirect(self.url(self.context, '@@index'))
         return
+
+class EtranzactQueryHistoryPageApplicant(UtilityView, grok.View):
+    """ Query history of eTranzact payments
+    """
+    grok.context(IApplicantOnlinePayment)
+    grok.name('query_history')
+    grok.require('waeup.payApplicant')
+
+    def update(self, confirmation_number=None):
+        if self.context.p_state == 'paid':
+            self.flash(_('This ticket has already been paid.'))
+            return
+        applicant = self.context.__parent__
+        if query_etranzact(confirmation_number, applicant, self.context, self):
+            actions_after_applicant_payment(applicant, self)
+        return
+
+    def render(self):
+        self.redirect(self.url(self.context, '@@index'))
+        return
Index: /main/waeup.uniben/trunk/src/waeup/uniben/interswitch/browser.py
===================================================================
--- /main/waeup.uniben/trunk/src/waeup/uniben/interswitch/browser.py	(revision 8246)
+++ /main/waeup.uniben/trunk/src/waeup/uniben/interswitch/browser.py	(revision 8247)
@@ -26,5 +26,5 @@
 from waeup.kofa.students.browser import write_log_message
 from waeup.kofa.students.viewlets import RequestCallbackActionButton
-from waeup.uniben.utils.utils import actions_after_payment
+from waeup.uniben.students.utils import actions_after_student_payment
 from waeup.uniben.interfaces import MessageFactory as _
 
Index: /main/waeup.uniben/trunk/src/waeup/uniben/payments/__init__.py
===================================================================
--- /main/waeup.uniben/trunk/src/waeup/uniben/payments/__init__.py	(revision 8247)
+++ /main/waeup.uniben/trunk/src/waeup/uniben/payments/__init__.py	(revision 8247)
@@ -0,0 +1,11 @@
+"""This package contains everything regarding payments.
+"""
+# Make this a package.
+from waeup.kofa.payments.container import PaymentsContainer
+from waeup.kofa.payments.payment import SCPayment, OnlinePayment
+
+__all__ = [
+    'PaymentsContainer',
+    'SCPayment',
+    'OnlinePayment',
+    ]
Index: /main/waeup.uniben/trunk/src/waeup/uniben/payments/interfaces.py
===================================================================
--- /main/waeup.uniben/trunk/src/waeup/uniben/payments/interfaces.py	(revision 8247)
+++ /main/waeup.uniben/trunk/src/waeup/uniben/payments/interfaces.py	(revision 8247)
@@ -0,0 +1,89 @@
+## $Id$
+##
+## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+from zope.interface import Attribute
+from zope import schema
+from waeup.kofa.payments.interfaces import IPayment
+from waeup.kofa.interfaces import MessageFactory as _
+
+class ICustomOnlinePayment(IPayment):
+    """A payment via payment gateways.
+
+    """
+
+    surcharge_1 = schema.Float(
+        title = _(u'Portal Fee'),
+        default = 0.0,
+        required = False,
+        readonly = True,
+        )
+
+    surcharge_2 = schema.Float(
+        title = _(u'Surcharge 2'),
+        default = 0.0,
+        required = False,
+        readonly = True,
+        )
+
+    surcharge_3 = schema.Float(
+        title = _(u'Surcharge 3'),
+        default = 0.0,
+        required = False,
+        readonly = True,
+        )
+
+    ac = schema.TextLine(
+        title = _(u'Activation Code'),
+        default = None,
+        required = False,
+        readonly = False,
+        )
+
+    r_amount_approved = schema.Float(
+        title = _(u'Response Amount Approved'),
+        default = 0.0,
+        required = False,
+        readonly = False,
+        )
+
+    r_desc = schema.TextLine(
+        title = _(u'Response Description'),
+        default = None,
+        required = False,
+        readonly = False,
+        )
+
+    r_pay_reference = schema.TextLine(
+        title = _(u'Response Payment Reference'),
+        default = None,
+        required = False,
+        readonly = False,
+        )
+
+    r_code = schema.TextLine(
+        title = _(u'Response Code'),
+        default = None,
+        required = False,
+        readonly = False,
+        )
+
+    r_card_num = schema.TextLine(
+        title = _(u'Response Card Number'),
+        default = None,
+        required = False,
+        readonly = False,
+        )
Index: /main/waeup.uniben/trunk/src/waeup/uniben/payments/payment.py
===================================================================
--- /main/waeup.uniben/trunk/src/waeup/uniben/payments/payment.py	(revision 8247)
+++ /main/waeup.uniben/trunk/src/waeup/uniben/payments/payment.py	(revision 8247)
@@ -0,0 +1,32 @@
+## $Id$
+##
+## Copyright (C) 2012 Uli Fouquet & Henrik Bettermann
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+"""
+These are the payment tickets.
+"""
+import grok
+from waeup.kofa.utils.helpers import attrs_to_fields
+from waeup.kofa.payments.payment import Payment
+from waeup.uniben.payments.interfaces import ICustomOnlinePayment
+
+class CustomOnlinePayment(Payment):
+    """This is an online payment.
+    """
+    grok.implements(ICustomOnlinePayment)
+    grok.provides(ICustomOnlinePayment)
+
+CustomOnlinePayment = attrs_to_fields(CustomOnlinePayment)
Index: /main/waeup.uniben/trunk/src/waeup/uniben/students/browser.py
===================================================================
--- /main/waeup.uniben/trunk/src/waeup/uniben/students/browser.py	(revision 8246)
+++ /main/waeup.uniben/trunk/src/waeup/uniben/students/browser.py	(revision 8247)
@@ -19,5 +19,7 @@
 from zope.formlib.textwidgets import BytesDisplayWidget
 from zope.component import getUtility
+from waeup.kofa.widgets.datewidget import FriendlyDatetimeDisplayWidget
 from waeup.kofa.interfaces import IExtFileStore
+from waeup.kofa.browser.layout import action
 from waeup.kofa.students.browser import (
     StudentPersonalDisplayFormPage,
@@ -25,13 +27,21 @@
     StudentClearanceDisplayFormPage, OnlinePaymentCallbackPage,
     ExportPDFClearanceSlipPage, StudentBaseManageFormPage,
-    StudentBaseEditFormPage, StudentPersonalEditFormPage)
+    StudentBaseEditFormPage, StudentPersonalEditFormPage,
+    OnlinePaymentDisplayFormPage, OnlinePaymentAddFormPage,
+    OnlinePaymentBreadcrumb)
 from waeup.kofa.students.viewlets import RequestCallbackActionButton
 from waeup.uniben.students.interfaces import (
     ICustomStudentBase, ICustomStudent, ICustomStudentPersonal,
     ICustomUGStudentClearance,ICustomPGStudentClearance,
+    ICustomStudentOnlinePayment,
     )
 from waeup.uniben.interfaces import MessageFactory as _
 
-class CustomRequestCallbackActionButton(RequestCallbackActionButton):
+class CustomOnlinePaymentBreadcrumb(OnlinePaymentBreadcrumb):
+    """A breadcrumb for payments.
+    """
+    grok.context(ICustomStudentOnlinePayment)
+
+class RequestCallbackActionButton(RequestCallbackActionButton):
     """ Do not display the base package callback button in custom pages.
     """
@@ -144,2 +154,30 @@
         return False
 
+class CustomOnlinePaymentDisplayFormPage(OnlinePaymentDisplayFormPage):
+    """ Page to view an online payment ticket
+    """
+    grok.context(ICustomStudentOnlinePayment)
+    form_fields = grok.AutoFields(ICustomStudentOnlinePayment)
+    form_fields[
+        'creation_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
+    form_fields[
+        'payment_date'].custom_widget = FriendlyDatetimeDisplayWidget('le')
+    grok.template('payment_view')
+
+    @property
+    def transaction_code(self):
+        tcode = self.context.p_id
+        return tcode[len(tcode)-8:len(tcode)]
+
+class CustomOnlinePaymentAddFormPage(OnlinePaymentAddFormPage):
+    """ Page to add an online payment ticket
+    """
+    form_fields = grok.AutoFields(ICustomStudentOnlinePayment).select(
+        'p_category')
+    factory = u'waeup.CustomStudentOnlinePayment'
+
+    def _fillCustomFields(self, payment, pay_details):
+        payment.surcharge_1 = pay_details['surcharge_1']
+        payment.surcharge_2 = pay_details['surcharge_2']
+        payment.surcharge_3 = pay_details['surcharge_3']
+        return payment
Index: /main/waeup.uniben/trunk/src/waeup/uniben/students/browser_templates/payment_view.pt
===================================================================
--- /main/waeup.uniben/trunk/src/waeup/uniben/students/browser_templates/payment_view.pt	(revision 8247)
+++ /main/waeup.uniben/trunk/src/waeup/uniben/students/browser_templates/payment_view.pt	(revision 8247)
@@ -0,0 +1,18 @@
+<table class="form-table" i18n:domain="waeup.uniben"
+  tal:define="files provider:files">
+  <tbody>
+    <tal:widgets content="structure provider:widgets" />
+    <tr tal:condition="python: files.replace('\n','')">
+      <td class="separator" colspan=2 i18n:translate="">
+        Uploaded Files
+      </td>
+    </tr>
+    <tal:files content="structure files" />
+    <tr>
+      <td class="fieldname">
+        <span i18n:translate="">Transaction Code</span>:
+      </td>
+      <td tal:content="view/transaction_code">TRANSACTIONCODE</td>
+    </tr>
+  </tbody>
+</table>
Index: /main/waeup.uniben/trunk/src/waeup/uniben/students/interfaces.py
===================================================================
--- /main/waeup.uniben/trunk/src/waeup/uniben/students/interfaces.py	(revision 8246)
+++ /main/waeup.uniben/trunk/src/waeup/uniben/students/interfaces.py	(revision 8247)
@@ -18,5 +18,5 @@
 from zope import schema
 from waeup.kofa.schema import TextLineChoice
-from waeup.kofa.interfaces import SimpleKofaVocabulary
+from waeup.kofa.interfaces import SimpleKofaVocabulary, academic_sessions_vocab
 from waeup.kofa.schema import FormattedDate
 from waeup.kofa.schoolgrades import ResultEntryField
@@ -31,4 +31,5 @@
     lgas_vocab, high_qual, high_grade, exam_types)
 from waeup.uniben.interfaces import MessageFactory as _
+from waeup.uniben.payments.interfaces import ICustomOnlinePayment
 
 class ICustomStudentBase(IStudentBase):
@@ -339,2 +340,7 @@
 
     """
+
+class ICustomStudentOnlinePayment(ICustomOnlinePayment):
+    """A student payment via payment gateways.
+
+    """
Index: /main/waeup.uniben/trunk/src/waeup/uniben/students/payments.py
===================================================================
--- /main/waeup.uniben/trunk/src/waeup/uniben/students/payments.py	(revision 8247)
+++ /main/waeup.uniben/trunk/src/waeup/uniben/students/payments.py	(revision 8247)
@@ -0,0 +1,57 @@
+## $Id$
+##
+## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+##
+"""
+Student payment components.
+"""
+import grok
+from zope.component.interfaces import IFactory
+from zope.interface import implementedBy
+from waeup.kofa.students.interfaces import IStudentNavigation
+from waeup.kofa.payments import PaymentsContainer, OnlinePayment
+from waeup.kofa.utils.helpers import attrs_to_fields
+from waeup.uniben.students.interfaces import ICustomStudentOnlinePayment
+
+class CustomStudentOnlinePayment(OnlinePayment):
+    """This is an online payment.
+    """
+    grok.implements(ICustomStudentOnlinePayment, IStudentNavigation)
+    grok.provides(ICustomStudentOnlinePayment)
+
+    def __init__(self):
+        super(CustomStudentOnlinePayment, self).__init__()
+        return
+
+    def getStudent(self):
+        return self.__parent__.__parent__
+
+CustomStudentOnlinePayment = attrs_to_fields(CustomStudentOnlinePayment)
+
+# Student online payments must be importable. So we might need a factory.
+class CustomStudentOnlinePaymentFactory(grok.GlobalUtility):
+    """A factory for student online payments.
+    """
+    grok.implements(IFactory)
+    grok.name(u'waeup.CustomStudentOnlinePayment')
+    title = u"Create a new online payment.",
+    description = u"This factory instantiates new online payment instances."
+
+    def __call__(self, *args, **kw):
+        return CustomStudentOnlinePayment()
+
+    def getInterfaces(self):
+        return implementedBy(CustomStudentOnlinePayment)
Index: /main/waeup.uniben/trunk/src/waeup/uniben/students/utils.py
===================================================================
--- /main/waeup.uniben/trunk/src/waeup/uniben/students/utils.py	(revision 8246)
+++ /main/waeup.uniben/trunk/src/waeup/uniben/students/utils.py	(revision 8247)
@@ -20,4 +20,5 @@
 from waeup.kofa.students.utils import StudentsUtils
 from waeup.kofa.students.interfaces import IStudentsUtils
+from waeup.kofa.accesscodes import create_accesscode
 from waeup.uniben.interfaces import MessageFactory as _
 
@@ -41,4 +42,32 @@
     else:
         return 0.0
+
+def actions_after_student_payment(student, payment, view):
+    if payment.p_category == 'clearance':
+        # Create CLR access code
+        pin, error = create_accesscode('CLR',0,student.student_id)
+        if error:
+            view.flash(_('Valid callback received. ${a}',
+                mapping = {'a':error}))
+            return
+        payment.ac = pin
+    elif payment.p_category == 'schoolfee':
+        # Create SFE access code
+        pin, error = create_accesscode('SFE',0,student.student_id)
+        if error:
+            view.flash(_('Valid callback received. ${a}',
+                mapping = {'a':error}))
+            return
+        payment.ac = pin
+    elif payment.p_category == 'bed_allocation':
+        # Create HOS access code
+        pin, error = create_accesscode('HOS',0,student.student_id)
+        if error:
+            view.flash(_('Valid callback received. ${a}',
+                mapping = {'a':error}))
+            return
+        payment.ac = pin
+    view.flash(_('Valid callback received.'))
+    return
 
 class CustomStudentsUtils(StudentsUtils):
Index: /main/waeup.uniben/trunk/src/waeup/uniben/utils/utils.py
===================================================================
--- /main/waeup.uniben/trunk/src/waeup/uniben/utils/utils.py	(revision 8246)
+++ /main/waeup.uniben/trunk/src/waeup/uniben/utils/utils.py	(revision 8247)
@@ -21,34 +21,5 @@
 import pytz
 from waeup.kofa.utils.utils import KofaUtils, sorted_phone_prefixes
-from waeup.kofa.accesscodes import create_accesscode
 from waeup.uniben.interfaces import MessageFactory as _
-
-def actions_after_payment(student, payment, view):
-    if payment.p_category == 'clearance':
-        # Create CLR access code
-        pin, error = create_accesscode('CLR',0,student.student_id)
-        if error:
-            view.flash(_('Valid callback received. ${a}',
-                mapping = {'a':error}))
-            return
-        payment.ac = pin
-    elif payment.p_category == 'schoolfee':
-        # Create SFE access code
-        pin, error = create_accesscode('SFE',0,student.student_id)
-        if error:
-            view.flash(_('Valid callback received. ${a}',
-                mapping = {'a':error}))
-            return
-        payment.ac = pin
-    elif payment.p_category == 'bed_allocation':
-        # Create HOS access code
-        pin, error = create_accesscode('HOS',0,student.student_id)
-        if error:
-            view.flash(_('Valid callback received. ${a}',
-                mapping = {'a':error}))
-            return
-        payment.ac = pin
-    view.flash(_('Valid callback received.'))
-    return
 
 INT_PHONE_PREFIXES = [
