Index: /main/waeup.sirp/trunk/src/waeup/sirp/students/browser.py
===================================================================
--- /main/waeup.sirp/trunk/src/waeup/sirp/students/browser.py	(revision 7590)
+++ /main/waeup.sirp/trunk/src/waeup/sirp/students/browser.py	(revision 7591)
@@ -36,9 +36,7 @@
     SIRPPage, SIRPEditFormPage, SIRPAddFormPage, SIRPDisplayFormPage,
     ContactAdminForm, SIRPForm)
-from waeup.sirp.browser.interfaces import ICaptchaManager, IBreadcrumbIgnorable
+from waeup.sirp.browser.interfaces import ICaptchaManager
 from waeup.sirp.browser.breadcrumbs import Breadcrumb
 from waeup.sirp.browser.resources import datepicker, datatable, tabs, warning
-from waeup.sirp.browser.viewlets import (
-    ManageActionButton, AddActionButton)
 from waeup.sirp.browser.layout import jsaction, action, UtilityView
 from waeup.sirp.interfaces import (
@@ -62,5 +60,4 @@
 from waeup.sirp.students.vocabularies import StudyLevelSource
 from waeup.sirp.browser.resources import toggleall
-from waeup.sirp.applicants.interfaces import IApplicantBaseData
 from waeup.sirp.hostels.hostel import NOT_OCCUPIED
 from waeup.sirp.utils.helpers import get_current_principal
@@ -248,12 +245,4 @@
         return
 
-class StudentsContainerManageActionButton(ManageActionButton):
-    grok.order(1)
-    grok.context(IStudentsContainer)
-    grok.view(StudentsContainerPage)
-    grok.require('waeup.manageStudent')
-    text = 'Manage student section'
-
-
 class StudentsContainerManagePage(SIRPPage):
     """The manage page for student containers.
@@ -304,12 +293,4 @@
         return
 
-class StudentsContainerAddActionButton(AddActionButton):
-    grok.order(1)
-    grok.context(IStudentsContainer)
-    grok.view(StudentsContainerManagePage)
-    grok.require('waeup.manageStudent')
-    text = 'Add student'
-    target = 'addstudent'
-
 class StudentAddFormPage(SIRPAddFormPage):
     """Add-form to add a student.
@@ -351,13 +332,4 @@
             return 'set'
         return 'unset'
-
-class ContactActionButton(ManageActionButton):
-    grok.order(4)
-    grok.context(IStudent)
-    grok.view(StudentBaseDisplayFormPage)
-    grok.require('waeup.manageStudent')
-    icon = 'actionicon_mail.png'
-    text = 'Send email'
-    target = 'contactstudent'
 
 class ContactStudentForm(ContactAdminForm):
@@ -397,12 +369,4 @@
         return
 
-class StudentBaseManageActionButton(ManageActionButton):
-    grok.order(1)
-    grok.context(IStudent)
-    grok.view(StudentBaseDisplayFormPage)
-    grok.require('waeup.manageStudent')
-    text = 'Manage'
-    target = 'manage_base'
-
 class StudentBaseManageFormPage(SIRPEditFormPage):
     """ View to manage student base data
@@ -484,51 +448,4 @@
         return '%s: Clearance Data' % self.context.display_fullname
 
-class StudentClearanceManageActionButton(ManageActionButton):
-    grok.order(1)
-    grok.context(IStudent)
-    grok.view(StudentClearanceDisplayFormPage)
-    grok.require('waeup.manageStudent')
-    text = 'Manage'
-    target = 'edit_clearance'
-
-class StudentClearActionButton(ManageActionButton):
-    grok.order(2)
-    grok.context(IStudent)
-    grok.view(StudentClearanceDisplayFormPage)
-    grok.require('waeup.clearStudent')
-    text = 'Clear student'
-    target = 'clear'
-    icon = 'actionicon_accept.png'
-
-    @property
-    def target_url(self):
-        if self.context.state != REQUESTED:
-            return ''
-        return self.view.url(self.view.context, self.target)
-
-class StudentRejectClearanceActionButton(ManageActionButton):
-    grok.order(3)
-    grok.context(IStudent)
-    grok.view(StudentClearanceDisplayFormPage)
-    grok.require('waeup.clearStudent')
-    text = 'Reject clearance'
-    target = 'reject_clearance'
-    icon = 'actionicon_reject.png'
-
-    @property
-    def target_url(self):
-        if self.context.state not in (REQUESTED, CLEARED):
-            return ''
-        return self.view.url(self.view.context, self.target)
-
-class ClearanceSlipActionButton(ManageActionButton):
-    grok.order(4)
-    grok.context(IStudent)
-    grok.view(StudentClearanceDisplayFormPage)
-    grok.require('waeup.viewStudent')
-    icon = 'actionicon_pdf.png'
-    text = 'Download clearance slip'
-    target = 'clearance.pdf'
-
 class ExportPDFClearanceSlipPage(grok.View):
     """Deliver a PDF slip of the context.
@@ -642,12 +559,4 @@
         return '%s: Personal Data' % self.context.display_fullname
 
-class StudentPersonalEditActionButton(ManageActionButton):
-    grok.order(1)
-    grok.context(IStudent)
-    grok.view(StudentPersonalDisplayFormPage)
-    grok.require('waeup.viewStudent')
-    text = 'Edit'
-    target = 'edit_personal'
-
 class StudentPersonalManageFormPage(SIRPEditFormPage):
     """ Page to edit student clearance data
@@ -698,12 +607,4 @@
             return self.context.certificate.__parent__.__parent__.__parent__
         return
-
-class StudyCourseManageActionButton(ManageActionButton):
-    grok.order(1)
-    grok.context(IStudentStudyCourse)
-    grok.view(StudyCourseDisplayFormPage)
-    grok.require('waeup.manageStudent')
-    text = 'Manage'
-    target = 'manage'
 
 class StudyCourseManageFormPage(SIRPEditFormPage):
@@ -809,13 +710,4 @@
             total_credits += val.credits
         return total_credits
-
-class CourseRegistrationSlipActionButton(ManageActionButton):
-    grok.order(1)
-    grok.context(IStudentStudyLevel)
-    grok.view(StudyLevelDisplayFormPage)
-    grok.require('waeup.viewStudent')
-    icon = 'actionicon_pdf.png'
-    text = 'Download course registration slip'
-    target = 'course_registration.pdf'
 
 class ExportPDFCourseRegistrationSlipPage(UtilityView, grok.View):
@@ -852,44 +744,4 @@
             tabledata=tabledata)
 
-class StudyLevelManageActionButton(ManageActionButton):
-    grok.order(2)
-    grok.context(IStudentStudyLevel)
-    grok.view(StudyLevelDisplayFormPage)
-    grok.require('waeup.manageStudent')
-    text = 'Manage'
-    target = 'manage'
-
-class StudentValidateCoursesActionButton(ManageActionButton):
-    grok.order(3)
-    grok.context(IStudentStudyLevel)
-    grok.view(StudyLevelDisplayFormPage)
-    grok.require('waeup.validateStudent')
-    text = 'Validate courses'
-    target = 'validate_courses'
-    icon = 'actionicon_accept.png'
-
-    @property
-    def target_url(self):
-        if self.context.getStudent().state != REGISTERED or \
-            str(self.context.__parent__.current_level) != self.context.__name__:
-            return ''
-        return self.view.url(self.view.context, self.target)
-
-class StudentRejectCoursesActionButton(ManageActionButton):
-    grok.order(4)
-    grok.context(IStudentStudyLevel)
-    grok.view(StudyLevelDisplayFormPage)
-    grok.require('waeup.validateStudent')
-    text = 'Reject courses'
-    target = 'reject_courses'
-    icon = 'actionicon_reject.png'
-
-    @property
-    def target_url(self):
-        if self.context.getStudent().state not in (VALIDATED, REGISTERED) or \
-            str(self.context.__parent__.current_level) != self.context.__name__:
-            return ''
-        return self.view.url(self.view.context, self.target)
-
 class StudyLevelManageFormPage(SIRPEditFormPage):
     """ Page to edit the student study level data
@@ -1058,12 +910,4 @@
             self.context.getStudent().display_fullname,self.context.code)
 
-class CourseTicketManageActionButton(ManageActionButton):
-    grok.order(1)
-    grok.context(ICourseTicket)
-    grok.view(CourseTicketDisplayFormPage)
-    grok.require('waeup.manageStudent')
-    text = 'Manage'
-    target = 'manage'
-
 class CourseTicketManageFormPage(SIRPEditFormPage):
     """ Page to manage course tickets
@@ -1162,12 +1006,4 @@
     def addPaymentTicket(self, **data):
         self.redirect(self.url(self.context, '@@addop'))
-
-#class OnlinePaymentManageActionButton(ManageActionButton):
-#    grok.order(1)
-#    grok.context(IStudentPaymentsContainer)
-#    grok.view(PaymentsDisplayFormPage)
-#    grok.require('waeup.manageStudent')
-#    text = 'Manage payments'
-#    target = 'manage'
 
 class OnlinePaymentAddFormPage(SIRPAddFormPage):
@@ -1243,34 +1079,4 @@
         return '%s: Online Payment Ticket %s' % (
             self.context.getStudent().display_fullname,self.context.p_id)
-
-class PaymentReceiptActionButton(ManageActionButton):
-    grok.order(1)
-    grok.context(IStudentOnlinePayment)
-    grok.view(OnlinePaymentDisplayFormPage)
-    grok.require('waeup.viewStudent')
-    icon = 'actionicon_pdf.png'
-    text = 'Download payment receipt'
-    target = 'payment_receipt.pdf'
-
-    @property
-    def target_url(self):
-        if self.context.p_state != 'paid':
-            return ''
-        return self.view.url(self.view.context, self.target)
-
-class RequestCallbackActionButton(ManageActionButton):
-    grok.order(2)
-    grok.context(IStudentOnlinePayment)
-    grok.view(OnlinePaymentDisplayFormPage)
-    grok.require('waeup.payStudent')
-    icon = 'actionicon_call.png'
-    text = 'Request callback'
-    target = 'callback'
-
-    @property
-    def target_url(self):
-        if self.context.p_state != 'unpaid':
-            return ''
-        return self.view.url(self.view.context, self.target)
 
 class OnlinePaymentCallbackPage(UtilityView, grok.View):
@@ -1420,13 +1226,4 @@
         return sa
 
-class AddBedTicketActionButton(ManageActionButton):
-    grok.order(1)
-    grok.context(IStudentAccommodation)
-    grok.view(AccommodationManageFormPage)
-    grok.require('waeup.handleAccommodation')
-    icon = 'actionicon_home.png'
-    text = 'Book accommodation'
-    target = 'add'
-
 class BedTicketAddPage(SIRPPage):
     """ Page to add an online payment ticket
@@ -1538,13 +1335,4 @@
         return 'Bed Ticket for Session %s' % self.context.getSessionString()
 
-class BedTicketSlipActionButton(ManageActionButton):
-    grok.order(1)
-    grok.context(IBedTicket)
-    grok.view(BedTicketDisplayFormPage)
-    grok.require('waeup.handleAccommodation')
-    icon = 'actionicon_pdf.png'
-    text = 'Download bed allocation slip'
-    target = 'bed_allocation.pdf'
-
 class ExportPDFBedTicketSlipPage(UtilityView, grok.View):
     """Deliver a PDF slip of the context.
@@ -1569,13 +1357,4 @@
             self, 'bed_allocation.pdf',
             self.context.getStudent(), studentview)
-
-class RelocateStudentActionButton(ManageActionButton):
-    grok.order(2)
-    grok.context(IBedTicket)
-    grok.view(BedTicketDisplayFormPage)
-    grok.require('waeup.manageHostels')
-    icon = 'actionicon_reload.png'
-    text = 'Relocate student'
-    target = 'relocate'
 
 class BedTicketRelocationPage(UtilityView, grok.View):
@@ -1661,36 +1440,4 @@
 # Pages for students only
 
-class StudentBaseActionButton(ManageActionButton):
-    grok.order(1)
-    grok.context(IStudent)
-    grok.view(StudentBaseDisplayFormPage)
-    grok.require('waeup.handleStudent')
-    text = 'Edit base data'
-    target = 'edit_base'
-
-class StudentPasswordActionButton(ManageActionButton):
-    grok.order(2)
-    grok.context(IStudent)
-    grok.view(StudentBaseDisplayFormPage)
-    grok.require('waeup.handleStudent')
-    icon = 'actionicon_key.png'
-    text = 'Change password'
-    target = 'change_password'
-
-class StudentPassportActionButton(ManageActionButton):
-    grok.order(3)
-    grok.context(IStudent)
-    grok.view(StudentBaseDisplayFormPage)
-    grok.require('waeup.handleStudent')
-    icon = 'actionicon_portrait.png'
-    text = 'Change portrait'
-    target = 'change_portrait'
-
-    @property
-    def target_url(self):
-        if self.context.state != 'admitted':
-            return ''
-        return self.view.url(self.view.context, self.target)
-
 class StudentBaseEditFormPage(SIRPEditFormPage):
     """ View to edit student base data
@@ -1752,19 +1499,4 @@
         return
 
-class StudentClearanceStartActionButton(ManageActionButton):
-    grok.order(1)
-    grok.context(IStudent)
-    grok.view(StudentClearanceDisplayFormPage)
-    grok.require('waeup.handleStudent')
-    icon = 'actionicon_start.gif'
-    text = 'Start clearance'
-    target = 'start_clearance'
-
-    @property
-    def target_url(self):
-        if self.context.state != 'admitted':
-            return ''
-        return self.view.url(self.view.context, self.target)
-
 class StartClearancePage(SIRPPage):
     grok.context(IStudent)
@@ -1832,18 +1564,4 @@
         return
 
-class StudentClearanceEditActionButton(ManageActionButton):
-    grok.order(1)
-    grok.context(IStudent)
-    grok.view(StudentClearanceDisplayFormPage)
-    grok.require('waeup.handleStudent')
-    text = 'Edit'
-    target = 'cedit'
-
-    @property
-    def target_url(self):
-        if self.context.clearance_locked:
-            return ''
-        return self.view.url(self.view.context, self.target)
-
 class StudentClearanceEditFormPage(StudentClearanceManageFormPage):
     """ View to edit student clearance data by student
@@ -1917,19 +1635,4 @@
         self.redirect(self.url(self.context))
         return
-
-class CourseRegistrationStartActionButton(ManageActionButton):
-    grok.order(1)
-    grok.context(IStudentStudyCourse)
-    grok.view(StudyCourseDisplayFormPage)
-    grok.require('waeup.handleStudent')
-    icon = 'actionicon_start.gif'
-    text = 'Start course registration'
-    target = 'start_course_registration'
-
-    @property
-    def target_url(self):
-        if not self.context.getStudent().state in (CLEARED,RETURNING):
-            return ''
-        return self.view.url(self.view.context, self.target)
 
 class StartCourseRegistrationPage(SIRPPage):
@@ -1982,23 +1685,4 @@
         return
 
-
-class AddStudyLevelActionButton(AddActionButton):
-    grok.order(1)
-    grok.context(IStudentStudyCourse)
-    grok.view(StudyCourseDisplayFormPage)
-    grok.require('waeup.handleStudent')
-    text = 'Add course list'
-    target = 'add'
-
-    @property
-    def target_url(self):
-        student = self.view.context.getStudent()
-        condition1 = student.state != 'school fee paid'
-        condition2 = str(student['studycourse'].current_level) in \
-            self.view.context.keys()
-        if condition1 or condition2:
-            return ''
-        return self.view.url(self.view.context, self.target)
-
 class AddStudyLevelFormPage(SIRPEditFormPage):
     """ Page for students to add current study levels
@@ -2037,22 +1721,4 @@
         self.redirect(self.url(self.context))
         return
-
-class StudyLevelEditActionButton(ManageActionButton):
-    grok.order(1)
-    grok.context(IStudentStudyLevel)
-    grok.view(StudyLevelDisplayFormPage)
-    grok.require('waeup.handleStudent')
-    text = 'Add and remove courses'
-    target = 'edit'
-
-    @property
-    def target_url(self):
-        student = self.view.context.getStudent()
-        condition1 = student.state != 'school fee paid'
-        condition2 = student[
-            'studycourse'].current_level != self.view.context.level
-        if condition1 or condition2:
-            return ''
-        return self.view.url(self.view.context, self.target)
 
 class StudyLevelEditFormPage(SIRPEditFormPage):
Index: /main/waeup.sirp/trunk/src/waeup/sirp/students/viewlets.py
===================================================================
--- /main/waeup.sirp/trunk/src/waeup/sirp/students/viewlets.py	(revision 7590)
+++ /main/waeup.sirp/trunk/src/waeup/sirp/students/viewlets.py	(revision 7591)
@@ -24,11 +24,23 @@
 from waeup.sirp.utils.helpers import string_from_bytes, file_size
 from waeup.sirp.browser import DEFAULT_IMAGE_PATH
-from waeup.sirp.browser.viewlets import PrimaryNavTab, PlainActionButton
+from waeup.sirp.browser.viewlets import (
+    PrimaryNavTab, ManageActionButton, AddActionButton)
 from waeup.sirp.browser.layout import default_primary_nav_template
+from waeup.sirp.students.workflow import (ADMITTED, PAID,
+    CLEARANCE, REQUESTED, RETURNING, CLEARED, REGISTERED, VALIDATED)
 from waeup.sirp.students.browser import (
-    StudentClearanceDisplayFormPage, StudentClearanceManageFormPage,
-    write_log_message, StudentBaseManageFormPage, StudentBaseDisplayFormPage,
-    StudentFilesUploadPage, ExportPDFClearanceSlipPage)
-from waeup.sirp.students.interfaces import IStudent, IStudentClearance
+    StudentClearanceManageFormPage,
+    write_log_message, StudentBaseManageFormPage,
+    StudentFilesUploadPage, ExportPDFClearanceSlipPage, StudentsContainerPage,
+    StudentsContainerManagePage, StudentBaseDisplayFormPage,
+    StudentClearanceDisplayFormPage, StudentPersonalDisplayFormPage,
+    StudyCourseDisplayFormPage, StudyLevelDisplayFormPage,
+    CourseTicketDisplayFormPage, OnlinePaymentDisplayFormPage,
+    AccommodationManageFormPage, BedTicketDisplayFormPage,)
+from waeup.sirp.students.interfaces import (
+    IStudentsContainer, IStudent, IStudentClearance,
+    IStudentStudyCourse, IStudentAccommodation, IStudentStudyLevel,
+    ICourseTicket, IStudentOnlinePayment, IBedTicket,
+    )
 
 grok.context(ISIRPObject) # Make ISIRPObject the default context
@@ -110,4 +122,334 @@
     link = 'history'
     text = u'History'
+
+
+class StudentsContainerManageActionButton(ManageActionButton):
+    grok.order(1)
+    grok.context(IStudentsContainer)
+    grok.view(StudentsContainerPage)
+    grok.require('waeup.manageStudent')
+    text = 'Manage student section'
+
+class StudentsContainerAddActionButton(AddActionButton):
+    grok.order(1)
+    grok.context(IStudentsContainer)
+    grok.view(StudentsContainerManagePage)
+    grok.require('waeup.manageStudent')
+    text = 'Add student'
+    target = 'addstudent'
+
+class ContactActionButton(ManageActionButton):
+    grok.order(4)
+    grok.context(IStudent)
+    grok.view(StudentBaseDisplayFormPage)
+    grok.require('waeup.manageStudent')
+    icon = 'actionicon_mail.png'
+    text = 'Send email'
+    target = 'contactstudent'
+
+class StudentBaseManageActionButton(ManageActionButton):
+    grok.order(1)
+    grok.context(IStudent)
+    grok.view(StudentBaseDisplayFormPage)
+    grok.require('waeup.manageStudent')
+    text = 'Manage'
+    target = 'manage_base'
+
+class StudentClearanceManageActionButton(ManageActionButton):
+    grok.order(1)
+    grok.context(IStudent)
+    grok.view(StudentClearanceDisplayFormPage)
+    grok.require('waeup.manageStudent')
+    text = 'Manage'
+    target = 'edit_clearance'
+
+class StudentClearActionButton(ManageActionButton):
+    grok.order(2)
+    grok.context(IStudent)
+    grok.view(StudentClearanceDisplayFormPage)
+    grok.require('waeup.clearStudent')
+    text = 'Clear student'
+    target = 'clear'
+    icon = 'actionicon_accept.png'
+
+    @property
+    def target_url(self):
+        if self.context.state != REQUESTED:
+            return ''
+        return self.view.url(self.view.context, self.target)
+
+class StudentRejectClearanceActionButton(ManageActionButton):
+    grok.order(3)
+    grok.context(IStudent)
+    grok.view(StudentClearanceDisplayFormPage)
+    grok.require('waeup.clearStudent')
+    text = 'Reject clearance'
+    target = 'reject_clearance'
+    icon = 'actionicon_reject.png'
+
+    @property
+    def target_url(self):
+        if self.context.state not in (REQUESTED, CLEARED):
+            return ''
+        return self.view.url(self.view.context, self.target)
+
+class ClearanceSlipActionButton(ManageActionButton):
+    grok.order(4)
+    grok.context(IStudent)
+    grok.view(StudentClearanceDisplayFormPage)
+    grok.require('waeup.viewStudent')
+    icon = 'actionicon_pdf.png'
+    text = 'Download clearance slip'
+    target = 'clearance.pdf'
+
+class StudentPersonalEditActionButton(ManageActionButton):
+    grok.order(1)
+    grok.context(IStudent)
+    grok.view(StudentPersonalDisplayFormPage)
+    grok.require('waeup.viewStudent')
+    text = 'Edit'
+    target = 'edit_personal'
+
+class StudyCourseManageActionButton(ManageActionButton):
+    grok.order(1)
+    grok.context(IStudentStudyCourse)
+    grok.view(StudyCourseDisplayFormPage)
+    grok.require('waeup.manageStudent')
+    text = 'Manage'
+    target = 'manage'
+
+class CourseRegistrationSlipActionButton(ManageActionButton):
+    grok.order(1)
+    grok.context(IStudentStudyLevel)
+    grok.view(StudyLevelDisplayFormPage)
+    grok.require('waeup.viewStudent')
+    icon = 'actionicon_pdf.png'
+    text = 'Download course registration slip'
+    target = 'course_registration.pdf'
+
+class StudyLevelManageActionButton(ManageActionButton):
+    grok.order(2)
+    grok.context(IStudentStudyLevel)
+    grok.view(StudyLevelDisplayFormPage)
+    grok.require('waeup.manageStudent')
+    text = 'Manage'
+    target = 'manage'
+
+class StudentValidateCoursesActionButton(ManageActionButton):
+    grok.order(3)
+    grok.context(IStudentStudyLevel)
+    grok.view(StudyLevelDisplayFormPage)
+    grok.require('waeup.validateStudent')
+    text = 'Validate courses'
+    target = 'validate_courses'
+    icon = 'actionicon_accept.png'
+
+    @property
+    def target_url(self):
+        if self.context.getStudent().state != REGISTERED or \
+            str(self.context.__parent__.current_level) != self.context.__name__:
+            return ''
+        return self.view.url(self.view.context, self.target)
+
+class StudentRejectCoursesActionButton(ManageActionButton):
+    grok.order(4)
+    grok.context(IStudentStudyLevel)
+    grok.view(StudyLevelDisplayFormPage)
+    grok.require('waeup.validateStudent')
+    text = 'Reject courses'
+    target = 'reject_courses'
+    icon = 'actionicon_reject.png'
+
+    @property
+    def target_url(self):
+        if self.context.getStudent().state not in (VALIDATED, REGISTERED) or \
+            str(self.context.__parent__.current_level) != self.context.__name__:
+            return ''
+        return self.view.url(self.view.context, self.target)
+
+class CourseTicketManageActionButton(ManageActionButton):
+    grok.order(1)
+    grok.context(ICourseTicket)
+    grok.view(CourseTicketDisplayFormPage)
+    grok.require('waeup.manageStudent')
+    text = 'Manage'
+    target = 'manage'
+
+#class OnlinePaymentManageActionButton(ManageActionButton):
+#    grok.order(1)
+#    grok.context(IStudentPaymentsContainer)
+#    grok.view(PaymentsDisplayFormPage)
+#    grok.require('waeup.manageStudent')
+#    text = 'Manage payments'
+#    target = 'manage'
+
+class PaymentReceiptActionButton(ManageActionButton):
+    grok.order(1)
+    grok.context(IStudentOnlinePayment)
+    grok.view(OnlinePaymentDisplayFormPage)
+    grok.require('waeup.viewStudent')
+    icon = 'actionicon_pdf.png'
+    text = 'Download payment receipt'
+    target = 'payment_receipt.pdf'
+
+    @property
+    def target_url(self):
+        if self.context.p_state != 'paid':
+            return ''
+        return self.view.url(self.view.context, self.target)
+
+class RequestCallbackActionButton(ManageActionButton):
+    grok.order(2)
+    grok.context(IStudentOnlinePayment)
+    grok.view(OnlinePaymentDisplayFormPage)
+    grok.require('waeup.payStudent')
+    icon = 'actionicon_call.png'
+    text = 'Request callback'
+    target = 'callback'
+
+    @property
+    def target_url(self):
+        if self.context.p_state != 'unpaid':
+            return ''
+        return self.view.url(self.view.context, self.target)
+
+class AddBedTicketActionButton(ManageActionButton):
+    grok.order(1)
+    grok.context(IStudentAccommodation)
+    grok.view(AccommodationManageFormPage)
+    grok.require('waeup.handleAccommodation')
+    icon = 'actionicon_home.png'
+    text = 'Book accommodation'
+    target = 'add'
+
+class BedTicketSlipActionButton(ManageActionButton):
+    grok.order(1)
+    grok.context(IBedTicket)
+    grok.view(BedTicketDisplayFormPage)
+    grok.require('waeup.handleAccommodation')
+    icon = 'actionicon_pdf.png'
+    text = 'Download bed allocation slip'
+    target = 'bed_allocation.pdf'
+
+class RelocateStudentActionButton(ManageActionButton):
+    grok.order(2)
+    grok.context(IBedTicket)
+    grok.view(BedTicketDisplayFormPage)
+    grok.require('waeup.manageHostels')
+    icon = 'actionicon_reload.png'
+    text = 'Relocate student'
+    target = 'relocate'
+
+class StudentBaseActionButton(ManageActionButton):
+    grok.order(1)
+    grok.context(IStudent)
+    grok.view(StudentBaseDisplayFormPage)
+    grok.require('waeup.handleStudent')
+    text = 'Edit base data'
+    target = 'edit_base'
+
+class StudentPasswordActionButton(ManageActionButton):
+    grok.order(2)
+    grok.context(IStudent)
+    grok.view(StudentBaseDisplayFormPage)
+    grok.require('waeup.handleStudent')
+    icon = 'actionicon_key.png'
+    text = 'Change password'
+    target = 'change_password'
+
+class StudentPassportActionButton(ManageActionButton):
+    grok.order(3)
+    grok.context(IStudent)
+    grok.view(StudentBaseDisplayFormPage)
+    grok.require('waeup.handleStudent')
+    icon = 'actionicon_portrait.png'
+    text = 'Change portrait'
+    target = 'change_portrait'
+
+    @property
+    def target_url(self):
+        if self.context.state != 'admitted':
+            return ''
+        return self.view.url(self.view.context, self.target)
+
+class StudentClearanceStartActionButton(ManageActionButton):
+    grok.order(1)
+    grok.context(IStudent)
+    grok.view(StudentClearanceDisplayFormPage)
+    grok.require('waeup.handleStudent')
+    icon = 'actionicon_start.gif'
+    text = 'Start clearance'
+    target = 'start_clearance'
+
+    @property
+    def target_url(self):
+        if self.context.state != 'admitted':
+            return ''
+        return self.view.url(self.view.context, self.target)
+
+class StudentClearanceEditActionButton(ManageActionButton):
+    grok.order(1)
+    grok.context(IStudent)
+    grok.view(StudentClearanceDisplayFormPage)
+    grok.require('waeup.handleStudent')
+    text = 'Edit'
+    target = 'cedit'
+
+    @property
+    def target_url(self):
+        if self.context.clearance_locked:
+            return ''
+        return self.view.url(self.view.context, self.target)
+
+class CourseRegistrationStartActionButton(ManageActionButton):
+    grok.order(1)
+    grok.context(IStudentStudyCourse)
+    grok.view(StudyCourseDisplayFormPage)
+    grok.require('waeup.handleStudent')
+    icon = 'actionicon_start.gif'
+    text = 'Start course registration'
+    target = 'start_course_registration'
+
+    @property
+    def target_url(self):
+        if not self.context.getStudent().state in (CLEARED,RETURNING):
+            return ''
+        return self.view.url(self.view.context, self.target)
+
+class AddStudyLevelActionButton(AddActionButton):
+    grok.order(1)
+    grok.context(IStudentStudyCourse)
+    grok.view(StudyCourseDisplayFormPage)
+    grok.require('waeup.handleStudent')
+    text = 'Add course list'
+    target = 'add'
+
+    @property
+    def target_url(self):
+        student = self.view.context.getStudent()
+        condition1 = student.state != 'school fee paid'
+        condition2 = str(student['studycourse'].current_level) in \
+            self.view.context.keys()
+        if condition1 or condition2:
+            return ''
+        return self.view.url(self.view.context, self.target)
+
+class StudyLevelEditActionButton(ManageActionButton):
+    grok.order(1)
+    grok.context(IStudentStudyLevel)
+    grok.view(StudyLevelDisplayFormPage)
+    grok.require('waeup.handleStudent')
+    text = 'Add and remove courses'
+    target = 'edit'
+
+    @property
+    def target_url(self):
+        student = self.view.context.getStudent()
+        condition1 = student.state != 'school fee paid'
+        condition2 = student[
+            'studycourse'].current_level != self.view.context.level
+        if condition1 or condition2:
+            return ''
+        return self.view.url(self.view.context, self.target)
 
 class StudentsTab(PrimaryNavTab):
