Index: main/waeup.kofa/trunk/src/waeup/kofa/applicants/browser.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/applicants/browser.py	(revision 8635)
+++ main/waeup.kofa/trunk/src/waeup/kofa/applicants/browser.py	(revision 8636)
@@ -36,5 +36,6 @@
     )
 from waeup.kofa.applicants.applicant import search
-from waeup.kofa.applicants.workflow import INITIALIZED, STARTED, PAID, SUBMITTED
+from waeup.kofa.applicants.workflow import (
+    INITIALIZED, STARTED, PAID, SUBMITTED, ADMITTED)
 from waeup.kofa.browser import (
     KofaPage, KofaEditFormPage, KofaAddFormPage, KofaDisplayFormPage,
@@ -545,6 +546,5 @@
 
 class CreateStudentPage(UtilityView, grok.View):
-    """Create a student object from applicatnt data
-    and copy applicant object.
+    """Create a student object from applicant data.
     """
     grok.context(IApplicant)
@@ -556,4 +556,40 @@
         self.flash(msg)
         self.redirect(self.url(self.context))
+        return
+
+    def render(self):
+        return
+
+class CreateAllStudentsPage(UtilityView, grok.View):
+    """Create all student objects from applicant data
+    in a container.
+
+    This is a hidden page, no link or button will
+    be provided and only PortalManagers can do this. 
+    """
+    grok.context(IApplicantsContainer)
+    grok.name('createallstudents')
+    grok.require('waeup.managePortal')
+
+    def update(self):
+        cat = getUtility(ICatalog, name='applicants_catalog')
+        results = list(cat.searchResults(state=(ADMITTED, ADMITTED)))
+        created = []
+        for result in results:
+            if not self.context.has_key(result.application_number):
+                continue
+            success, msg = result.createStudent(view=self)
+            if success:
+                created.append(result.applicant_id)
+            else:
+                ob_class = self.__implemented__.__name__.replace('waeup.kofa.','')
+                self.context.__parent__.logger_info(
+                    ob_class,result.applicant_id,msg)
+        if len(created):
+            self.flash(_('${a} students successfully created.',
+                mapping = {'a': len(created)}))
+        else:
+            self.flash(_('No student could be created.'))
+        self.redirect(self.url(self.context, u'@@manage')+'?tab2')
         return
 
Index: main/waeup.kofa/trunk/src/waeup/kofa/applicants/tests/test_applicantcopier.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/applicants/tests/test_applicantcopier.py	(revision 8635)
+++ main/waeup.kofa/trunk/src/waeup/kofa/applicants/tests/test_applicantcopier.py	(revision 8636)
@@ -20,5 +20,7 @@
 """
 import os
+import grok
 from hurry.workflow.interfaces import IWorkflowInfo, IWorkflowState
+from zope.event import notify
 from zope.component import getUtility
 from zope.i18n import translate
@@ -35,5 +37,5 @@
         return
 
-    def test_copier(self):
+    def prepare_applicant(self):
         self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
         self.browser.open(self.manage_path)
@@ -47,4 +49,8 @@
         file_ctrl.add_file(file_obj, filename='my_photo.jpg')
         self.browser.getControl("Save").click() # submit form
+        return
+
+    def test_copier(self):
+        self.prepare_applicant()
         storage = getUtility(IExtFileStore)
         file_id = IFileStoreNameChooser(self.applicant).chooseName()
@@ -100,15 +106,5 @@
 
     def test_batch_copying(self):
-        self.browser.addHeader('Authorization', 'Basic mgr:mgrpw')
-        self.browser.open(self.manage_path)
-        self.fill_correct_values()
-        self.browser.getControl("Save").click()
-        # Upload a passport picture
-        ctrl = self.browser.getControl(name='form.passport')
-        file_obj = open(
-            os.path.join(os.path.dirname(__file__), 'test_image.jpg'),'rb')
-        file_ctrl = ctrl.mech_control
-        file_ctrl.add_file(file_obj, filename='my_photo.jpg')
-        self.browser.getControl("Save").click() # submit form
+        self.prepare_applicant()
         IWorkflowState(self.applicant).setState('admitted')
         self.browser.getControl(name="form.course_admitted").value = ['CERT1']
@@ -120,4 +116,31 @@
         ctrl.getControl(value=self.applicant.application_number).selected = True
         self.browser.getControl("Create students from selected", index=0).click()
+        self.assertTrue('1 students successfully created' in self.browser.contents)
+
+    def test_hidden_batch_copying(self):
+        logfile = os.path.join(
+            self.app['datacenter'].storage, 'logs', 'applicants.log')
+        self.prepare_applicant()
+        self.browser.open(self.container_path + '/createallstudents')
+        self.assertTrue('No student could be created' in self.browser.contents)
+        IWorkflowState(self.applicant).setState('admitted')
+        notify(grok.ObjectModifiedEvent(self.applicant))
+        self.browser.open(self.container_path + '/createallstudents')
+        self.assertTrue('No student could be created' in self.browser.contents)
+        logcontent = open(logfile).read()
+        self.assertTrue('No course admitted provided' in logcontent)
+        self.browser.open(self.manage_path)
+        self.browser.getControl(name="form.course_admitted").value = ['CERT1']
+        self.browser.getControl("Save").click()
+        # date_of_birth is not required for applicants but for students
+        self.applicant.date_of_birth = None
+        self.browser.open(self.container_path + '/createallstudents')
+        self.assertTrue('No student could be created' in self.browser.contents)
+        logcontent = open(logfile).read()
+        self.assertTrue('RequiredMissing: date_of_birth' in logcontent)
+        self.browser.open(self.manage_path)
+        self.browser.getControl(name="form.date_of_birth").value = '09/09/1988'
+        self.browser.getControl("Save").click()
+        self.browser.open(self.container_path + '/createallstudents')
         self.assertTrue('1 students successfully created' in self.browser.contents)
 
