Index: main/waeup.kofa/trunk/src/waeup/kofa/interfaces.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/interfaces.py	(revision 11588)
+++ main/waeup.kofa/trunk/src/waeup/kofa/interfaces.py	(revision 11589)
@@ -668,4 +668,13 @@
         )
 
+    next_matric_integer = schema.Int(
+        title = _(u'Next Matriculation Number Integer'),
+        description = _(u'Integer used for constructing the next '
+                         'matriculation number'),
+        default = 0,
+        readonly = False,
+        required = False,
+        )
+
 class ISessionConfiguration(IKofaObject):
     """A session configuration object.
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/interfaces.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/interfaces.py	(revision 11588)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/interfaces.py	(revision 11589)
@@ -89,4 +89,23 @@
         """
 
+    def setMatricNumber(student):
+        """Set matriculation number of student.
+
+        If the student's matric number is unset a new matric number is
+        constructed using the next_matric_integer attribute of
+        the site configuration container and according to the
+        matriculation number construction rules defined in the
+        _constructMatricNumber method. The new matric number is set,
+        the students catalog updated and next_matric_integer
+        increased by one.
+
+        This method is tested but not used in the base package. It can
+        be used in custom packages by adding respective views
+        and by customizing _composeMatricNumber according to the
+        university's matriculation number construction rules.
+
+        The method can be disabled by setting next_matric_integer to zero.
+        """
+
     def getAccommodation_details(student):
         """Determine the accommodation dates of a student.
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_utils.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_utils.py	(revision 11588)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_utils.py	(revision 11589)
@@ -1,5 +1,7 @@
 # -*- coding: utf-8 -*-
 import unittest
-from zope.component import getUtility
+import grok
+from zope.component import getUtility, queryUtility, createObject
+from zope.catalog.interfaces import ICatalog
 from waeup.kofa.students.interfaces import IStudentsUtils
 from waeup.kofa.students.utils import formatted_text
@@ -37,2 +39,36 @@
         # In this case current_level remains unchanged and no error is raised.
         self.assertEqual(self.student['studycourse'].current_level, 600)
+
+    def test_setMatricNumber(self):
+        site = grok.getSite()
+        utils = getUtility(IStudentsUtils)
+        msg, mnumber = utils.setMatricNumber(self.student)
+        self.assertEqual(msg, 'Matriculation number cannot be set.')
+        self.assertEqual(mnumber, None)
+        site['configuration'].next_matric_integer = 1
+        msg, mnumber = utils.setMatricNumber(self.student)
+        self.assertEqual(msg, 'Matriculation number already set.')
+        self.assertEqual(mnumber, None)
+        self.assertEqual(self.student.matric_number, '234')
+        self.student.matric_number = None
+        msg, mnumber = utils.setMatricNumber(self.student)
+        self.assertEqual(msg, None)
+        self.assertEqual(mnumber, 1)
+        self.assertEqual(self.student.matric_number, '1')
+        self.assertEqual(site['configuration'].next_matric_integer, 2)
+        # Student can be found in catalog.
+        cat = queryUtility(ICatalog, name='students_catalog')
+        results = list(cat.searchResults(matric_number=('1', '1')))
+        self.assertEqual(self.student,results[0])
+        # Add another student.
+        another_student = createObject('waeup.Student')
+        another_student.matric_number = u'2'
+        self.app['students'].addStudent(another_student)
+        # Matric number can't be assigned twice.
+        self.student.matric_number = None
+        msg, mnumber = utils.setMatricNumber(self.student)
+        self.assertEqual(msg, 'Matriculation number exists.')
+        self.assertEqual(mnumber, None)
+        self.assertEqual(self.student.matric_number, None)
+        return
+
Index: main/waeup.kofa/trunk/src/waeup/kofa/students/utils.py
===================================================================
--- main/waeup.kofa/trunk/src/waeup/kofa/students/utils.py	(revision 11588)
+++ main/waeup.kofa/trunk/src/waeup/kofa/students/utils.py	(revision 11589)
@@ -25,4 +25,5 @@
 from reportlab.lib.styles import getSampleStyleSheet
 from reportlab.platypus import Paragraph, Image, Table, Spacer
+from zope.event import notify
 from zope.schema.interfaces import ConstraintNotSatisfied
 from zope.component import getUtility, createObject
@@ -35,5 +36,5 @@
 from waeup.kofa.students.interfaces import IStudentsUtils
 from waeup.kofa.students.workflow import ADMITTED
-from waeup.kofa.students.vocabularies import StudyLevelSource
+from waeup.kofa.students.vocabularies import StudyLevelSource, MatNumNotInSource
 from waeup.kofa.browser.pdf import (
     ENTRY1_STYLE, format_html, NOTE_STYLE, HEADING_STYLE, 
@@ -515,4 +516,39 @@
         return None, payment
 
+    def _constructMatricNumber(self, student, next_integer):
+        return unicode(next_integer)
+
+    def setMatricNumber(self, student):
+        """Set matriculation number of student.
+
+        If the student's matric number is unset a new matric number is
+        constructed using the next_matric_integer attribute of
+        the site configuration container and according to the
+        matriculation number construction rules defined in the
+        _constructMatricNumber method. The new matric number is set,
+        the students catalog updated and next_matric_integer
+        increased by one.
+
+        This method is tested but not used in the base package. It can
+        be used in custom packages by adding respective views
+        and by customizing _composeMatricNumber according to the
+        university's matriculation number construction rules.
+
+        The method can be disabled by setting next_matric_integer to zero.
+        """
+        next_integer = grok.getSite()['configuration'].next_matric_integer
+        if next_integer == 0:
+            return _('Matriculation number cannot be set.'), None
+        if student.matric_number is not None:
+            return _('Matriculation number already set.'), None
+        try:
+            student.matric_number = self._constructMatricNumber(
+                student, next_integer)
+        except MatNumNotInSource:
+            return _('Matriculation number exists.'), None
+        notify(grok.ObjectModifiedEvent(student))
+        grok.getSite()['configuration'].next_matric_integer += 1
+        return None, next_integer
+
     def getAccommodationDetails(self, student):
         """Determine the accommodation data of a student.
