Changeset 7133 for main/waeup.sirp


Ignore:
Timestamp:
18 Nov 2011, 08:48:22 (13 years ago)
Author:
Henrik Bettermann
Message:

Add fields email and phone which can be edited via the StudentBaseEditFormPage?. email, phone and passport picture are required for starting clearance.

Location:
main/waeup.sirp/trunk/src/waeup/sirp/students
Files:
5 edited

Legend:

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

    r7127 r7133  
    2222from zope.event import notify
    2323from zope.catalog.interfaces import ICatalog
    24 from zope.component import queryUtility
     24from zope.component import queryUtility, getUtility
    2525from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState
    2626from zope.component import createObject
     
    3434from waeup.sirp.browser.viewlets import (
    3535    ManageActionButton, PrimaryNavTab, AddActionButton)
    36 from waeup.sirp.interfaces import IWAeUPObject, IUserAccount
     36from waeup.sirp.interfaces import IWAeUPObject, IUserAccount, IExtFileStore
    3737from waeup.sirp.widgets.datewidget import (
    3838    FriendlyDateWidget, FriendlyDateDisplayWidget,
     
    6262    return
    6363
    64 # Save function used for save methods in manager pages
     64# Save function used for save methods in pages
    6565def msave(view, **data):
    6666    form = view.request.form
     
    7474    if fields_string:
    7575        write_log_message(view, 'saved: %s' % fields_string)
     76    return
     77
     78def emitLockMessage(view):
     79    view.flash('The requested form is locked (read-only).')
     80    view.redirect(view.url(view.context))
    7681    return
    7782
     
    364369    grok.require('waeup.manageStudents')
    365370    text = 'Manage'
    366     target = 'edit_base'
     371    target = 'manage_base'
    367372
    368373class StudentBaseManageFormPage(WAeUPEditFormPage):
    369     """ View to edit student base data
    370     """
    371     grok.context(IStudent)
    372     grok.name('edit_base')
     374    """ View to manage student base data
     375    """
     376    grok.context(IStudent)
     377    grok.name('manage_base')
    373378    grok.require('waeup.manageStudents')
    374379    form_fields = grok.AutoFields(IStudentBase).omit('student_id')
     
    409414                write_log_message(self, 'password changed')
    410415
     416        # The following is now done by contextual_reg_num_source validation
    411417        #self.reg_number = form.get('form.reg_number', None)
    412418        #if self.reg_number:
     
    14481454# Pages for students only
    14491455
     1456class StudentBaseActionButton(ManageActionButton):
     1457    grok.order(1)
     1458    grok.context(IStudent)
     1459    grok.view(StudentBaseDisplayFormPage)
     1460    grok.require('waeup.handleStudent')
     1461    text = 'Edit base data'
     1462    target = 'edit_base'
     1463
    14501464class StudentPasswordActionButton(ManageActionButton):
    1451     grok.order(1)
     1465    grok.order(2)
    14521466    grok.context(IStudent)
    14531467    grok.view(StudentBaseDisplayFormPage)
     
    14581472
    14591473class StudentPassportActionButton(ManageActionButton):
    1460     grok.order(1)
     1474    grok.order(3)
    14611475    grok.context(IStudent)
    14621476    grok.view(StudentBaseDisplayFormPage)
     
    14651479    text = 'Change portrait'
    14661480    target = 'change_portrait'
     1481
     1482    @property
     1483    def target_url(self):
     1484        if self.context.state != 'admitted':
     1485            return ''
     1486        return self.view.url(self.view.context, self.target)
     1487
     1488class StudentBaseEditFormPage(WAeUPEditFormPage):
     1489    """ View to edit student base data
     1490    """
     1491    grok.context(IStudent)
     1492    grok.name('edit_base')
     1493    grok.require('waeup.handleStudent')
     1494    form_fields = grok.AutoFields(IStudentBase).select(
     1495        'email', 'phone')
     1496    #grok.template('basemanagepage')
     1497    label = 'Edit base data'
     1498    title = 'Base Data'
     1499    pnav = 4
     1500
     1501    @grok.action('Save')
     1502    def save(self, **data):
     1503        msave(self, **data)
     1504        return
    14671505
    14681506class StudentPasswordSetting(grok.Adapter):
     
    15431581    pnav = 4
    15441582
     1583    def update(self):
     1584        if self.context.getStudent().state != 'admitted':
     1585            emitLockMessage(self)
     1586            return
     1587        super(StudentFilesUploadPage, self).update()
     1588        return
     1589
    15451590class StudentClearanceStartActionButton(ManageActionButton):
    15461591    grok.order(1)
     
    15701615    buttonname = 'Start clearance now'
    15711616
     1617    @property
     1618    def all_required_fields_filled(self):
     1619        if self.context.email and self.context.phone:
     1620            return True
     1621        return False
     1622
     1623    @property
     1624    def portrait_uploaded(self):
     1625        store = getUtility(IExtFileStore)
     1626        if store.getFileByContext(self.context, attr=u'passport.jpg'):
     1627            return True
     1628        return False
     1629
    15721630    def update(self, SUBMIT=None):
    15731631        if not self.context.state == 'admitted':
    15741632            self.flash("Wrong state.")
    15751633            self.redirect(self.url(self.context))
     1634            return
     1635        if not self.portrait_uploaded:
     1636            self.flash("No portrait uploaded.")
     1637            self.redirect(self.url(self.context, 'change_portrait'))
     1638            return
     1639        if not self.all_required_fields_filled:
     1640            self.flash("Not all required fields filled.")
     1641            self.redirect(self.url(self.context, 'edit_base'))
    15761642            return
    15771643        self.ac_series = self.request.form.get('ac_series', None)
     
    16301696    form_fields['date_of_birth'].custom_widget = FriendlyDateWidget('le-year')
    16311697
    1632     def emitLockMessage(self):
    1633         self.flash('The requested form is locked (read-only).')
    1634         self.redirect(self.url(self.context))
    1635         return
    1636 
    16371698    def update(self):
    16381699        if self.context.clearance_locked:
    1639             self.emitLockMessage()
    1640             return
    1641         datepicker.need()
     1700            emitLockMessage(self)
     1701            return
    16421702        return super(StudentClearanceEditFormPage, self).update()
    16431703
     
    17931853        return 'Add current level %s' % title
    17941854
    1795     def emitLockMessage(self):
    1796         self.flash('The requested form is locked (read-only).')
    1797         self.redirect(self.url(self.context))
    1798         return
    1799 
    18001855    def update(self):
    18011856        if self.context.getStudent().state != 'school fee paid':
    1802             self.emitLockMessage()
     1857            emitLockMessage(self)
    18031858            return
    18041859        super(AddStudyLevelFormPage, self).update()
  • main/waeup.sirp/trunk/src/waeup/sirp/students/interfaces.py

    r7124 r7133  
    11##
    22## interfaces.py
     3import re
    34from datetime import datetime
    45from zope.interface import Attribute, invariant
     
    1415from waeup.sirp.payments.interfaces import IPaymentsContainer, IOnlinePayment
    1516
     17# Define a valiation method for email addresses
     18class NotAnEmailAddress(schema.ValidationError):
     19    __doc__ = u"Invalid email address"
     20
     21check_email = re.compile(
     22    r"[a-zA-Z0-9._%-]+@([a-zA-Z0-9-]+.)*[a-zA-Z]{2,4}").match
     23def validate_email(value):
     24    if not check_email(value):
     25        raise NotAnEmailAddress(value)
     26    return True
     27
    1628class IStudentsContainer(IWAeUPObject):
    1729    """A students container contains university students.
     
    139151        required = False,
    140152        readonly = True,
     153        )
     154
     155    email = schema.ASCIILine(
     156        title = u'Email',
     157        required = False,
     158        constraint=validate_email,
     159        )
     160    phone = schema.Int(
     161        title = u'Phone',
     162        description = u'Enter phone number with country code and without spaces.',
     163        required = False,
    141164        )
    142165
  • main/waeup.sirp/trunk/src/waeup/sirp/students/tests/sample_student_data.csv

    r6844 r7133  
    1 firstname,lastname,fullname,reg_number,date_of_birth,matric_number
    2 Aaren,Pieri,Aaren Pieri,1,1990-01-02,100000
    3 Aaren,Finau,Aaren Finau,2,1990-01-03,100001
    4 Aaren,Berson,Aaren Berson,3,1990-01-04,100002
     1firstname,lastname,fullname,reg_number,date_of_birth,matric_number,email,phone
     2Aaren,Pieri,Aaren Pieri,1,1990-01-02,100000,aa@aa.ng,1234
     3Aaren,Finau,Aaren Finau,2,1990-01-03,100001,aa@aa.ng,1234
     4Aaren,Berson,Aaren Berson,3,1990-01-04,100002,aa@aa.ng,1234
  • main/waeup.sirp/trunk/src/waeup/sirp/students/tests/test_browser.py

    r7127 r7133  
    9191        student.matric_number = u'234'
    9292        student.sex = u'm'
     93        student.email = 'aa@aa.ng'
     94        student.phone = 1234
    9395        self.app['students'].addStudent(student)
    9496        self.student_id = student.student_id
     
    104106        self.add_student_path = self.container_path + '/addstudent'
    105107        self.student_path = self.container_path + '/' + self.student_id
    106         self.manage_student_path = self.student_path + '/edit_base'
     108        self.manage_student_path = self.student_path + '/manage_base'
    107109        self.clearance_student_path = self.student_path + '/view_clearance'
    108110        self.personal_student_path = self.student_path + '/view_personal'
     
    584586        # Prepare a csv file for students
    585587        open('students.csv', 'wb').write(
    586 """firstname,lastname,fullname,reg_number,date_of_birth,matric_number
    587 Aaren,Pieri,Aaren Pieri,1,1990-01-02,100000
    588 Claus,Finau,Claus Finau,2,1990-01-03,100001
    589 Brit,Berson,Brit Berson,3,1990-01-04,100001
     588"""firstname,lastname,fullname,reg_number,date_of_birth,matric_number,email,phone
     589Aaren,Pieri,Aaren Pieri,1,1990-01-02,100000,aa@aa.ng,1234
     590Claus,Finau,Claus Finau,2,1990-01-03,100001,aa@aa.ng,1234
     591Brit,Berson,Brit Berson,3,1990-01-04,100001,aa@aa.ng,1234
    590592""")
    591593        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
     
    757759        self.browser.getLink("Clearance Data").click()
    758760        self.browser.getLink("Start clearance").click()
     761        self.student.email = None
     762        # Uups, we forgot to fill the email fields
     763        self.browser.getControl("Start clearance").click()
     764        self.assertMatches('...Not all required fields filled...',
     765                           self.browser.contents)
     766        self.student.email = 'aa@aa.ng'
     767        self.browser.open(self.student_path + '/start_clearance')
    759768        self.browser.getControl(name="ac_series").value = '3'
    760769        self.browser.getControl(name="ac_number").value = '4444444'
     
    923932        ac = self.app['accesscodes']['CLR-0'][pin]
    924933        ac.owner = self.student_id
    925         # The new CLR-0 pin can be used for starting clearance
    926         IWorkflowInfo(self.student).fireTransition('admit')
    927         self.browser.open(self.student_path + '/start_clearance')
    928         parts = pin.split('-')[1:]
    929         clrseries, clrnumber = parts
    930         self.browser.getControl(name="ac_series").value = clrseries
    931         self.browser.getControl(name="ac_number").value = clrnumber
    932         self.browser.getControl("Start clearance now").click()
    933         self.assertMatches('...Clearance process has been started...',
    934                            self.browser.contents)
    935934        return
    936935
     
    975974
    976975        # The new CLR-0 pin can be used for starting clearance
     976        # but they have to upload a passport picture first
     977        # which is only possible in state admitted
     978        self.browser.open(self.student_path + '/change_portrait')
     979        self.assertMatches('...form is locked...',
     980                          self.browser.contents)
    977981        IWorkflowInfo(self.student).fireTransition('admit')
     982        self.browser.open(self.student_path + '/change_portrait')
     983        pseudo_image = StringIO('I pretend to be a graphics file')
     984        ctrl = self.browser.getControl(name='passportuploadedit')
     985        file_ctrl = ctrl.mech_control
     986        file_ctrl.add_file(pseudo_image, filename='my_photo.jpg')
     987        self.browser.getControl(
     988            name='upload_passportuploadedit').click()
    978989        self.browser.open(self.student_path + '/start_clearance')
    979990        parts = pin.split('-')[1:]
  • main/waeup.sirp/trunk/src/waeup/sirp/students/workflow.py

    r6990 r7133  
    176176def handle_student_transition_event(obj, event):
    177177    """Append message to student history and log file when transition happened.
     178
     179      Lock and unlock clearance form.
    178180    """
    179181    msg = '%s' % event.transition.user_data['msg']
Note: See TracChangeset for help on using the changeset viewer.