Index: /main/waeup.sirp/trunk/src/waeup/sirp/students/browser.py
===================================================================
--- /main/waeup.sirp/trunk/src/waeup/sirp/students/browser.py	(revision 6698)
+++ /main/waeup.sirp/trunk/src/waeup/sirp/students/browser.py	(revision 6699)
@@ -70,4 +70,6 @@
 from waeup.sirp.students.student import Student
 from waeup.sirp.students.catalog import search
+from waeup.sirp.accesscodes import invalidate_accesscode, get_access_code
+from waeup.sirp.accesscodes.workflow import USED
 
 class StudentsTab(PrimaryNavTab):
@@ -142,4 +144,54 @@
         return
 
+class SetPassword(WAeUPPage):
+    grok.context(IWAeUPObject)
+    grok.name('setpassword')
+    grok.require('waeup.Public')
+    title = ''
+    label = 'Set password for first-time login'
+    acprefix = 'PWD'
+    pnav = 4
+
+    def update(self, SUBMIT=None):
+        self.reg_number = self.request.form.get('form.reg_number', None)
+        # We must not use form.ac_series and form.ac_number in forms since these
+        # are interpreted by applicant credentials
+        self.acseries = self.request.form.get('form.acseries', None)
+        self.acnumber = self.request.form.get('form.acnumber', None)
+        
+        if SUBMIT is None:
+            return
+        hitlist = search(query=self.reg_number,
+            searchtype='reg_number', view=self)
+        if not hitlist:
+            self.flash('No student found.')
+            return
+        if len(hitlist) != 1:   # Cannot happen but anyway
+            self.flash('More than one student found.')
+            return
+        self.student_id = hitlist[0].student_id
+        student_pw = hitlist[0].context.password
+        if student_pw:
+            self.flash('Password has already been set. Please request a password reset.')
+            return
+        pin = '%s-%s-%s' % (self.acprefix,self.acseries,self.acnumber)
+        code = get_access_code(pin)
+        if not code:
+            self.flash('Access code is invalid.')
+            return
+        # Mark pin as used (this also fires a pin related transition)
+        # and set student password
+        if code.state == USED:
+            self.flash('Access code has already been used.')
+            return
+        else:
+            comment = u"AC invalidated"
+            # Here we know that the ac is in state initialized so we do not
+            # expect an exception
+            #import pdb; pdb.set_trace()
+            invalidate_accesscode(pin,comment)
+            IUserAccount(hitlist[0].context).setPassword(self.acnumber)
+        return
+
 class StudentsContainerManageActionButton(ManageActionButton):
     grok.order(1)
@@ -234,5 +286,5 @@
     grok.require('waeup.viewStudent')
     grok.template('basepage')
-    form_fields = grok.AutoFields(IStudentBase).omit('password')
+    form_fields = grok.AutoFields(IStudentBase)  #.omit('password')
     pnav = 4
     title = 'Base Data'
@@ -241,4 +293,10 @@
     def label(self):
         return '%s: Base Data' % self.context.name
+
+    @property
+    def hasPassword(self):
+        if self.context.password:
+            return 'set'
+        return 'unset'
 
 class StudentBaseManageActionButton(ManageActionButton):
@@ -289,10 +347,14 @@
             transition_id = form['transition']
             self.wf_info.fireTransition(transition_id)
+        if form.has_key('password') and form['password']:
+            IUserAccount(self.context).setPassword(form['password'])
+            if fields_string:
+                fields_string += ' + password'
+            else:
+                fields_string = 'password'
         self.flash('Form has been saved.')
         ob_class = self.__implemented__.__name__.replace('waeup.sirp.','')
         if fields_string:
             self.context.loggerInfo(ob_class, 'saved: % s' % fields_string)
-        if 'password' in fields_string:
-            IUserAccount(self.context).setPassword(form['form.password'])
         return
 
@@ -496,11 +558,15 @@
         fields_string = '+'.join(' + '.join(str(i) for i in b) for b in changed_fields)
         self.context._p_changed = True
+        form = self.request.form
+        if form.has_key('password') and form['password']:
+            IUserAccount(self.context).setPassword(form['password'])
+            if fields_string:
+                fields_string += ' + password'
+            else:
+                fields_string = 'password'
         self.flash('Form has been saved.')
-        form = self.request.form
         ob_class = self.__implemented__.__name__.replace('waeup.sirp.','')
         if fields_string:
             self.context.loggerInfo(ob_class, 'saved: % s' % fields_string)
-        if 'password' in fields_string:
-            IUserAccount(self.context).setPassword(form['form.password'])
         return
 
Index: /main/waeup.sirp/trunk/src/waeup/sirp/students/browser_templates/baseeditpage.pt
===================================================================
--- /main/waeup.sirp/trunk/src/waeup/sirp/students/browser_templates/baseeditpage.pt	(revision 6698)
+++ /main/waeup.sirp/trunk/src/waeup/sirp/students/browser_templates/baseeditpage.pt	(revision 6699)
@@ -38,4 +38,10 @@
         </tr>
       </tal:block>
+      <tr>
+        <td class="label"><label>Password:</label></td>
+        <td>
+          <input name="password" type="password" tal:attributes="value view/context/password" />
+        </td>
+      </tr>
     </tbody>
   </table>
Index: /main/waeup.sirp/trunk/src/waeup/sirp/students/browser_templates/basemanagepage.pt
===================================================================
--- /main/waeup.sirp/trunk/src/waeup/sirp/students/browser_templates/basemanagepage.pt	(revision 6698)
+++ /main/waeup.sirp/trunk/src/waeup/sirp/students/browser_templates/basemanagepage.pt	(revision 6699)
@@ -39,4 +39,10 @@
       </tal:block>
       <tr>
+        <td class="label"><label>Password:</label></td>
+        <td>
+          <input name="password" type="password" tal:attributes="value view/context/password" />
+        </td>
+      </tr>
+      <tr>
         <td class="label"><label>Registration Transition:</label></td>
         <td>
Index: /main/waeup.sirp/trunk/src/waeup/sirp/students/browser_templates/basepage.pt
===================================================================
--- /main/waeup.sirp/trunk/src/waeup/sirp/students/browser_templates/basepage.pt	(revision 6699)
+++ /main/waeup.sirp/trunk/src/waeup/sirp/students/browser_templates/basepage.pt	(revision 6699)
@@ -0,0 +1,34 @@
+<h2 i18n:translate=""
+    tal:condition="view/label"
+    tal:content="view/label">Label</h2>
+
+<table class="zebra">
+  <tbody>
+    <tal:block repeat="widget view/widgets">
+      <tr>
+        <td class="fieldname">
+          <tal:block content="widget/label"/>:
+        </td>
+        <td>
+          <input tal:replace="structure widget" />
+        </td>
+      </tr>
+    </tal:block>
+    <tr>
+      <td class="fieldname">
+          Password:
+      </td>
+      <td>
+          <tal:password replace="view/hasPassword" />
+      </td>
+    <tr>
+  </tbody>
+  <tfoot>
+    <tr class="controls">
+      <td colspan="2" class="align-right">
+        <input tal:repeat="action view/actions"
+               tal:replace="structure action/render" />
+      </td>
+    </tr>
+  </tfoot>
+</table>
Index: /main/waeup.sirp/trunk/src/waeup/sirp/students/browser_templates/setpassword.pt
===================================================================
--- /main/waeup.sirp/trunk/src/waeup/sirp/students/browser_templates/setpassword.pt	(revision 6699)
+++ /main/waeup.sirp/trunk/src/waeup/sirp/students/browser_templates/setpassword.pt	(revision 6699)
@@ -0,0 +1,39 @@
+<h2 i18n:translate=""  tal:condition="view/label"  tal:content="view/label">Label</h2>
+<form method="POST">
+  <input type="hidden" name="form.acprefix"  value="" tal:attributes="value view/acprefix" />
+  <table>
+    <tbody>
+      <tr> <td>
+          <label for="form.reg_number">Registration Number:
+          </label></td> <td>
+          <input name="form.reg_number" type="text" size="15" maxlength="15"  value="" tal:attributes="value view/reg_number"/> </td>
+      </tr>
+      <tr>
+        <tr> <td>
+            <label for="form.acseries">Access Code:
+            </label></td> <td>
+            <span tal:replace="view/acprefix">PIN Prefix
+            </span> -
+            <input name="form.acseries" type="text" size="3" maxlength="3"  value="" tal:attributes="value view/acseries"/> -
+            <input name="form.acnumber" type="text" size="10" maxlength="10"  value="" tal:attributes="value view/acnumber" /> </td>
+        </tr>
+        <tr>
+          <td colspan="2">
+            <input type="submit" name="SUBMIT" value="Show Student Id and set Password" /> </td>
+        </tr>
+    </tbody>
+  </table>
+</form>
+<div> <h3>Instructions:</h3>
+  <ul class="list">
+    <li> Purchase a Password Access Code (PWD PIN).
+    </li>
+    <li> Enter your (JAMB) Registration Number and the Access Code.
+    </li>
+    <li> After pressing the button, your Student Id will be displayed and your Password set.
+        The new password is the 10-digit part of the access code just used.
+    </li>
+    <li> Go to the general login page and enter your new credentials.
+    </li>
+  </ul>
+</div>
Index: /main/waeup.sirp/trunk/src/waeup/sirp/students/interfaces.py
===================================================================
--- /main/waeup.sirp/trunk/src/waeup/sirp/students/interfaces.py	(revision 6698)
+++ /main/waeup.sirp/trunk/src/waeup/sirp/students/interfaces.py	(revision 6699)
@@ -62,4 +62,5 @@
     state = Attribute('Returns the registration state of a student')
     #student_id = Attribute('Randomly generated id')
+    password = Attribute('Encrypted password of a student')
 
     def loggerInfo(ob_class, comment):
@@ -76,9 +77,4 @@
         default = u'Nobody',
         required = True,
-        )
-
-    password = schema.Password(
-        title = u'Password',
-        required = False,
         )
 
@@ -152,9 +148,4 @@
         )
 
-    password = schema.Password(
-        title = u'Password',
-        required = True,
-        )
-
 IStudentBaseEdit['name'].order =  IStudentBase['name'].order
 
Index: /main/waeup.sirp/trunk/src/waeup/sirp/students/student.py
===================================================================
--- /main/waeup.sirp/trunk/src/waeup/sirp/students/student.py	(revision 6698)
+++ /main/waeup.sirp/trunk/src/waeup/sirp/students/student.py	(revision 6699)
@@ -45,4 +45,5 @@
         except ComponentLookupError:
             self.student_id = u'Z654321'
+        self.password = None
         return
 
Index: /main/waeup.sirp/trunk/src/waeup/sirp/students/tests/test_browser.py
===================================================================
--- /main/waeup.sirp/trunk/src/waeup/sirp/students/tests/test_browser.py	(revision 6698)
+++ /main/waeup.sirp/trunk/src/waeup/sirp/students/tests/test_browser.py	(revision 6699)
@@ -205,7 +205,10 @@
         self.browser.getControl(name="transition").value = ['admit']
         self.browser.getControl(name="form.name").value = 'John Tester'
-        self.browser.getControl(name="form.password").value = 'secret'
+        self.browser.getControl(name="form.reg_number").value = '123'
+        self.browser.getControl(name="password").value = 'secret'
         self.browser.getControl("Save").click()
-        self.assertTrue('Form has been saved' in self.browser.contents)
+        self.assertMatches('...Form has been saved...',
+                           self.browser.contents)
+        #self.assertTrue('Form has been saved' in self.browser.contents)
 
         self.browser.open(self.student_path)
@@ -262,5 +265,5 @@
         # Change password
         self.browser.getLink("Change password").click()
-        self.browser.getControl(name="form.password").value = 'new_password'
+        self.browser.getControl(name="password").value = 'new_password'
         self.browser.getControl("Save").click()
         self.assertTrue('Form has been saved' in self.browser.contents)
@@ -276,5 +279,5 @@
         self.browser.open(self.login_path)
         self.browser.getControl(name="form.login").value = self.test_student_id
-        self.browser.getControl(name="form.password").value = 'new_password'
+        self.browser.getControl(name="password").value = 'new_password'
         self.browser.getControl("Login").click()
         self.assertEqual(self.browser.url, self.student_path)
