Index: WAeUP_SRP/base/skins/waeup_student/add_course_result.py
===================================================================
--- WAeUP_SRP/base/skins/waeup_student/add_course_result.py	(revision 2439)
+++ WAeUP_SRP/base/skins/waeup_student/add_course_result.py	(revision 2448)
@@ -64,8 +64,15 @@
 
 
-cr_id = context.invokeFactory('StudentCourseResult',course_id)
-cr = getattr(context,cr_id)
-context.portal_workflow.doActionFor(cr,'open')
-cr.getContent().edit(mapping=d)
+# cr_id = context.invokeFactory('StudentCourseResult',course_id)
+# cr = getattr(context,cr_id)
+# context.portal_workflow.doActionFor(cr,'open')
+# cr.getContent().edit(mapping=d)
+d['course_id'] = course_id
+d['student_id'] = student_id = context.getStudentId()
+d['level_id'] = level_id = context.getId()
+d['session_id'] = context.session
+d['key'] = "%s|%s|%s" % (student_id,level_id,course_id)
+
+context.course_results.addRecord(**d)
 #context.portal_workflow.doActionFor(cr,'close')
 #args['course_id'] = course_id
@@ -73,6 +80,6 @@
 logger.info('%s added StudentCourseResult object %s at level %s for %s' % (member,
                                                                            course_id,
-                                                                           context.getId(),
-                                                                           context.getStudentId()))
+                                                                           level_id,
+                                                                           student_id))
 
 psm = "You successfully added course %s!" % course_id
@@ -83,3 +90,2 @@
     url = context.absolute_url() + '?' + urlencode(args)
 return REQUEST.RESPONSE.redirect(url)
-
Index: WAeUP_SRP/base/skins/waeup_student/course_edit.py
===================================================================
--- WAeUP_SRP/base/skins/waeup_student/course_edit.py	(revision 2439)
+++ WAeUP_SRP/base/skins/waeup_student/course_edit.py	(revision 2448)
@@ -10,64 +10,75 @@
 """
 """
-wf = context.portal_workflow
+try:
+    from Products.zdb import set_trace
+except:
+    def set_trace():
+        pass
 from urllib import urlencode
 from Products.CPSDocument.utils import getFormUidUrlArg
+from Products.AdvancedQuery import Eq, Between, Le,In
 import DateTime
 current = DateTime.DateTime()
 import logging
 logger = logging.getLogger('Skins.course_edit')
+wf = context.portal_workflow
+request = REQUEST
+edit = "edit" in request.form.keys()
+mtool = context.portal_membership
+member = mtool.getAuthenticatedMember()
+member_id = str(member)
+requested_id = context.getStudentId()
+if requested_id and not context.isStaff() and member_id != requested_id:
+    logger.info('%s tried to access personal object of %s' % (member_id,requested_id))
+    student_id = requested_id
+    return REQUEST.RESPONSE.redirect("%s/srp_anonymous_view" % context.portal_url())
+elif context.isStaff():
+    student_id = requested_id
+else:
+    student_id = member_id
+    
+level_id = context.getId()
+course_id = traverse_subpath[0]
+query = Eq('student_id',student_id) &\
+        Eq('level_id', level_id) &\
+        Eq('code', course_id)
 
-info = context.getCourseResultInfo()
+course_results = context.course_results.evalAdvancedQuery(query)
+mode = 'edit'
+object = {}
+course = course_results[0]
+for field in context.course_results.schema():
+    object[field] = getattr(course,field)
+lt = context.portal_layouts
+res,psm, ds = lt.renderLayout(schema_id = 'student_course_result',
+                               layout_id = 'student_course_result_fe',
+                               layout_mode = mode,
+                               context=context,
+                               mapping=edit and REQUEST,
+                               ob=object,
+                               commit = False)
 
-if info is None:
-    logger.info('Anonymous user tried to access %s' % REQUEST.get('URL0'))
-    return REQUEST.RESPONSE.redirect("%s/srp_anonymous_view" % context.portal_url())
+while True:
+    if psm == 'invalid':
+        psm = "Please correct your input"
+        break
+    elif psm == '':
+        break
+    if edit:
+        data = {}
+        dm = ds.getDataModel()
+        for field in context.course_results.schema():
+            if dm.has_key("%s" % field):
+                data[field] = dm.get(field)
+        data['key'] = object['key']
+        context.course_results.modifyRecord(**data)
+        logger.info('%s edited course result data %s' % (student_id, course_id))
+        psm = 'psm_content_changed'
+        break
 
-student = info['student']
-#per = info['per']
-course_doc = info['course_doc']
-state = info['review_state']
-result_state = wf.getInfoFor(context,'review_state',None)
-if result_state == "closed":
-    try:
-        context.portal_workflow.doActionFor(context,'open')
-    except:
-        pass
+return context.course_edit_form(rendered = res,
+                                psm = psm,
+                                mode = mode,
+                                ds = ds,
+                               )
 
-is_valid, ds = course_doc.validate(request=REQUEST,
-                                schema_id = 'student_course_result',
-                                layout_id = 'student_course_result_fe',
-                                proxy=context,
-                                use_session=True)
-
-psm = ""
-args = {}
-action = "/course_edit_form"
-base_url = context.absolute_url()
-
-if is_valid:
-    if cpsdocument_edit_button:
-        #name = "%(firstname)s %(middlename)s %(lastname)s" % ds
-        #name = name.strip()
-        #name = name.replace('  ',' ')
-        #email = ds.get('email')
-        #phone = ds.get('phone')
-        #student_id = context.getStudentId()
-        #context.students_catalog.modifyRecord(id = student_id,
-        #                                      name = name,
-        #                                      email = email,
-        #                                      phone = phone,
-        #                                      sex = ds.get('sex'),
-        #                                     )
-        logger.info('%s (%s) edited course result data %s' % (info['id'],info['review_state'],context.id))
-        #action = ""
-        #base_url = student.absolute_url()
-        #url = base_url + action
-        psm = 'psm_content_changed'
-else:
-    psm = 'psm_content_error'
-    args = getFormUidUrlArg(REQUEST)
-
-args['portal_status_message'] = psm
-url = base_url + action + '?' + urlencode(args)
-REQUEST.RESPONSE.redirect(url)
Index: WAeUP_SRP/base/skins/waeup_student/course_edit_form.pt
===================================================================
--- WAeUP_SRP/base/skins/waeup_student/course_edit_form.pt	(revision 2439)
+++ WAeUP_SRP/base/skins/waeup_student/course_edit_form.pt	(revision 2448)
@@ -1,41 +1,28 @@
-<metal:body use-macro="here/slip_template/macros/master">
+<tal:block define="rendered_main options/rendered;
+           portal_status_message options/psm;
+           ds options/ds;
+           mode options/mode;
+           course_id python:traverse_subpath[0];
+           "
+           >
+  <metal:block define-macro="edit_form">
+    <metal:block use-macro="here/slip_template/macros/master">
+      <metal:block fill-slot="main">
+        <h3>Update Your Course <span tal:content="course_id" /> </h3>
+        <br />            
+        
+        <form action="ACTION" method="post" id="editForm"
+              enctype="multipart/form-data" class="workflow"
+              tal:attributes="action string:${context/absolute_url}/course_edit/${course_id}">
+          <span tal:omit-tag="" tal:replace="structure rendered_main"/>
+          <br/>
+          <input type="submit" class="standalone" 
+                 name="edit"
+                 value="Save" 
+                 id="edit"/>
+        </form>
+      </metal:block>
+    </metal:block>
+  </metal:block>
+</tal:block>
 
-    <metal:main fill-slot="main"
-                  tal:define="info context/getCourseResultInfo;">
-      <metal:block tal:condition="not: info">
-        <span tal:content="here/illegal_view" />
-      </metal:block>
-      <metal:block tal:condition="info">
-      <metal:block tal:define="rendered_main python:info['course_doc'].render(
-                              layout_mode='edit',
-                              schema_id = 'student_course_result',
-                              layout_id = 'student_course_result_fe',
-                              request=request, 
-                              use_session=True,);
-           form_action string:course_edit;
-           edition python:True;
-           metadata nothing;
-            ">
-    <h3>Update Your Course <span tal:content='here/id' /> </h3>
-    <br />            
-            
-    <form action="ACTION" method="post" id="editForm"
-          enctype="multipart/form-data" class="workflow"
-          tal:attributes="action form_action">
-      <span tal:condition="not: info">
-        <metal:block use-macro="here/error_not_found/macros/not_found" />
-      </span>
-      <span tal:condition="info">
-        <span tal:omit-tag="" tal:replace="structure rendered_main"/>
-      </span>
-      <br/>
-      <input type="submit" class="standalone" 
-             name="cpsdocument_edit_button"
-             value="Save" 
-             id="cpsdocument_edit_button"/>
-    </form>
-    </metal:block>
-    </metal:block>    
-    </metal:main>
-</metal:body>
-
Index: WAeUP_SRP/base/skins/waeup_student/create_level.py
===================================================================
--- WAeUP_SRP/base/skins/waeup_student/create_level.py	(revision 2439)
+++ WAeUP_SRP/base/skins/waeup_student/create_level.py	(revision 2448)
@@ -64,20 +64,18 @@
     level.getContent().edit(mapping={'session': current_session})
     context.portal_workflow.doActionFor(level,'close_for_edit')
-    context.waeup_tool.doCommit()
-results = []
+    #context.waeup_tool.doCommit()
+level_id = level.getId()
+student_id = context.getStudentId()
+session_id = context.getLevelSession(level.getContent(),student_id,level_id)
+
 if student.matric_no:
     results = context.results_import(matric_no = student.matric_no)
+records = []
 if results:
-    #carry_overs = [brain for brain in results if brain.GRADE in ('D','E','F')]
     l = []
     carry_overs = results
-
-    # carry_overs for probation students: yes or not, that is the question
-    #if student.verdict == "C": # on probation
-    #    carry_overs = []
-
     for co in carry_overs:
-        cr_id = "%s_co" % co.CosCode
-        if level.hasObject(cr_id):    #already created
+        course_id = co.CosCode
+        if level.hasObject(course_id):    #already created
             continue
         carry_over = False
@@ -96,5 +94,5 @@
             except:
                 # logger.info('%s, course %s has invalid score %s"' % (student.id,
-                #                                                     co.CosCode,
+                #                                                     course_id,
                 #                                                     co.Score))
                 continue
@@ -104,34 +102,54 @@
         if not carry_over:
             continue
+        if course_id in l:
+            # don't add twice
+            continue
+        l += course_id,
         d = context.getCourseInfo(co.CosCode)
+        d['course_id'] = course_id
         d['grade'] = co.GRADE
-        d['carry_level'] = co.CarryLevel
-        cr_id = level.invokeFactory('StudentCourseResult',"%s_co" % co.CosCode)
-        course_result = getattr(level,cr_id)
-        context.portal_workflow.doActionFor(course_result,'open')
-        course_result.getContent().edit(mapping=d)
-        context.waeup_tool.doCommit()
+        d['carry_over'] = carry_over
+        # course_id = level.invokeFactory('StudentCourseResult',"%s_co" % course_id)
+        # course_result = getattr(level,course_id)
+        # context.portal_workflow.doActionFor(course_result,'open')
+        # course_result.getContent().edit(mapping=d)
+        # context.waeup_tool.doCommit()
+        d['code'] = course_id
+        d['student_id'] = student_id
+        d['level_id'] = level_id
+        d['session_id'] = session_id
+        records.append(d)
+
 #level['create_course_results'](cert_id,current_level)
 res = context.portal_catalog(portal_type="Certificate", id = cert_id)
-l = []
 if res:
     cert = res[0]
     path = cert.getPath()
-    #set_trace()
     query = Eq("path","%s/%s" % (path,current_level)) &\
             Eq('portal_type','CertificateCourse')
     courses = aq_portal(query)
     for c in courses:
-        cr_id = "%s" % c.getId
-        if level.hasObject(cr_id):    #already created
+        course_id = "%s" % c.getId
+        if course_id in l:
+            # don't add twice
             continue
+        l += course_id,
         d = context.getCourseInfo(c.getId)
-        cr_id = level.invokeFactory('StudentCourseResult',c.getId)
-        course_result = getattr(level,cr_id)
-        context.portal_workflow.doActionFor(course_result,'open')
-        #d['core_or_elective'] = getattr(c.getObject().getContent(),'core_or_elective')
-        d['core_or_elective'] = True
-        course_result.getContent().edit(mapping=d)
-        context.waeup_tool.doCommit()
+        # course_id = level.invokeFactory('StudentCourseResult',c.getId)
+        # course_result = getattr(level,course_id)
+        # context.portal_workflow.doActionFor(course_result,'open')
+        # d['core_or_elective'] = True
+        # course_result.getContent().edit(mapping=d)
+        # context.waeup_tool.doCommit()
+        d['carry_over'] = False
+        d['core_or_elective'] = getattr(c.getObject().getContent(),'core_or_elective')
+        d['course_id'] = course_id
+        d['student_id'] = student_id = context.getStudentId()
+        d['level_id'] = level_id
+        d['session_id'] = session_id
+        #context.course_results.addRecord(**d)
+        records.append(d)
+if records:
+    context.course_results.addMultipleRecords(records)
 logger.info('%s finished to create level %s' % (student.id,current_level))
 
@@ -147,3 +165,2 @@
 
 return response.redirect("%s/%s" % (context.absolute_url(),current_level))
-
Index: WAeUP_SRP/base/skins/waeup_student/delete_course_result.py
===================================================================
--- WAeUP_SRP/base/skins/waeup_student/delete_course_result.py	(revision 2439)
+++ WAeUP_SRP/base/skins/waeup_student/delete_course_result.py	(revision 2448)
@@ -27,21 +27,11 @@
 
 message = ''
+student_id = context.getStudentId()
 if ids:
-    real_ids = []
-    for id in ids:
-        if context.hasObject(id):
-            real_ids.append(id)
-    for cr_id in real_ids:
-        cr = getattr(context,cr_id)
-        if wf.getInfoFor(cr,'review_state',None) == "closed":
-            context.portal_workflow.doActionFor(cr,'open')
-    if real_ids:
-        try:
-            context.manage_delObjects(real_ids)
-            logger.info('%s deleted StudentCourseResult object %s for %s' % (member,id,context.getStudentId()))
-            message = 'psm_item(s)_deleted'
-        except Unauthorized:
-            logger.info('%s has no permission to delete StudentCourseResult objects for %s' % (member,context.getStudentId()))
-            message = 'no item(s) deleted'
+    sid_level = "%s|%s" % (student_id,context.getId())
+    for key in ['%s|%s' % (sid_level,id) for id in ids]:
+        context.course_results.deleteRecord(key)
+    logger.info('%s deleted CourseResults  %s for %s' % (member,ids,student_id))
+    message = 'psm_item(s)_deleted'
 else:
     message = 'psm_select_at_least_one_document'
Index: WAeUP_SRP/base/skins/waeup_student/getStudyLevelInfo.py
===================================================================
--- WAeUP_SRP/base/skins/waeup_student/getStudyLevelInfo.py	(revision 2439)
+++ WAeUP_SRP/base/skins/waeup_student/getStudyLevelInfo.py	(revision 2448)
@@ -25,12 +25,15 @@
 
 
-from Products.AdvancedQuery import Eq, Between, Le,In
-try:
-    aq_portal = context.portal_catalog.evalAdvancedQuery
-except:
-    aq_portal = context.portal_catalog_real.evalAdvancedQuery
+# from Products.AdvancedQuery import Eq, Between, Le,In
+# try:
+#     aq_portal = context.portal_catalog.evalAdvancedQuery
+# except:
+#     aq_portal = context.portal_catalog_real.evalAdvancedQuery
+course_results = context.course_results
 request = context.REQUEST
 #session = request.SESSION
 response = request.RESPONSE
+import logging
+logger = logging.getLogger('Skins.getStudyLevelInfo')
 
 def calculateGPA():
@@ -61,4 +64,5 @@
 
 student_id = context.getStudentId()
+level_id = context.getId()
 
 info = {}
@@ -85,51 +89,17 @@
         info['status_info'] = "Courses validated"
 info['doc'] = context.getContent()
-##study_course = context.aq_parent.getContent()
-##cert_id = study_course.study_course
 cert_id = student.course
 info['cert_id'] = cert_id
-normal = []
-carry_overs = []
-credits_total = 0
-for id,obj in context.objectItems():
-    #try:
-    #    credit = int(obj.getContent().credits)
-    #except ValueError:
-    #    credit = 3
-    #credits_total += credit
-    if not id:
-        continue
-    if id.endswith('_co'):
-        d = context.getCourseInfo(id[:-3])
-        try:
-            credits_total += int(d['credits'])
-        except ValueError:
-            credits_total += 0
-        d['id'] = id
-        d['grade'] = obj.getContent().grade
-        carry_overs.append(d)
-    else:
-        d = context.getCourseInfo(id)
-        d['id'] = id
-        coe = getattr(obj.getContent(),'core_or_elective',True)
-        d['coe'] = 'Core'
-        try:
-            credits_total += int(d['credits'])
-        except ValueError:
-            credits_total += 0
-        if not coe:
-            d['coe'] = 'Elective'
-        normal.append(d)
+if context.objectIds():
+    course_results.moveResultsHere(context,student_id)
+    logger.info("%s moved courseresults and deleted objects in level %s" % (student_id,level_id))
+credits_total,carry_overs,normal = course_results.getCourses(student_id,level_id)
 info['credits_total'] = credits_total
-max_credits = 50
-if context.getId() == student.end_level:
-    max_credits = 51
-info['max_credits'] = max_credits
-info['credits_exceeded'] = credits_total > max_credits
+info['credits_exceeded'] = credits_total > 51
 current_session = student.session
 info['submission_allowed']= not info['credits_exceeded'] and current_session == context.getSessionId()[-2:]
-carry_overs.sort(cmp_semester_id)
+# carry_overs.sort(cmp_semester_id)
 info['carry_overs'] = carry_overs
-normal.sort(cmp_semester_id)
+# normal.sort(cmp_semester_id)
 info['normal'] = normal
 
Index: WAeUP_SRP/base/skins/waeup_student/level_delete.py
===================================================================
--- WAeUP_SRP/base/skins/waeup_student/level_delete.py	(revision 2439)
+++ WAeUP_SRP/base/skins/waeup_student/level_delete.py	(revision 2448)
@@ -47,5 +47,8 @@
     #     evtool = getPublicEventService(here)
     #     evtool.notifyEvent('workflow_delete', ob, {})
+    for level_id in ids:
+        context.course_results.deleteResultsHere(level_id,student_id)
     here.manage_delObjects(ids)
+    
     message = 'portal_status_message=psm_item(s)_deleted'
 else:
Index: WAeUP_SRP/base/skins/waeup_student/refresh_level.py
===================================================================
--- WAeUP_SRP/base/skins/waeup_student/refresh_level.py	(revision 2439)
+++ WAeUP_SRP/base/skins/waeup_student/refresh_level.py	(revision 2448)
@@ -91,13 +91,19 @@
     courses = aq_portal(query)
     course_ids = [c.getId  for c in courses if c.getId not in level.objectIds()]
-    for c_id in course_ids:
+    for course_id in course_ids:
         #set_trace()
-        d = context.getCourseInfo(c_id)
-        cr_id = level.invokeFactory('StudentCourseResult',c_id)
-        course_result = getattr(level,cr_id)
-        context.portal_workflow.doActionFor(course_result,'open')
+        d = context.getCourseInfo(course_id)
+        # cr_id = level.invokeFactory('StudentCourseResult',c_id)
+        # course_result = getattr(level,cr_id)
+        # context.portal_workflow.doActionFor(course_result,'open')
+        # course_result.getContent().edit(mapping=d)
+        # context.waeup_tool.doCommit()
         d['core_or_elective'] = getattr(c.getObject().getContent(),'core_or_elective')
-        course_result.getContent().edit(mapping=d)
-        context.waeup_tool.doCommit()
+        #d['core_or_elective'] = True
+        d['course_id'] = course_id
+        d['student_id'] = student_id = context.getStudentId()
+        d['level_id'] = level_id = context.getId()
+        d['key'] = "%s|%s|%s" % (student_id,level_id,course_id)
+        context.course_results.addRecord(**d)
 #session.set('in_progress','finished')
 logger.info('%s updated course list' % member)
Index: WAeUP_SRP/base/skins/waeup_student/study_level_view.pt
===================================================================
--- WAeUP_SRP/base/skins/waeup_student/study_level_view.pt	(revision 2439)
+++ WAeUP_SRP/base/skins/waeup_student/study_level_view.pt	(revision 2448)
@@ -55,9 +55,11 @@
                    />
           </td>
-          <td width="78%" tal:content="row/title"></td>
+          <td width="66%" tal:content="row/title"></td>
           <td align="center" width="10%" tal:content="row/code"></td>
           <td align="center" width="2%">S<span tal:content="row/semester" /></td>
           <td align="center" width="2%" tal:content="row/credits"></td>
-          <td align="center" width="8%" tal:content="row/grade|string:"></td>
+          <td align="center" width="10%"> <span tal:content="row/coe|nothing" /></td>
+          <td tal:condition="python:review_state == 'school_fee_paid'" align="center" width="5%">&nbsp;</td>
+       
         </tr>
       </table>
@@ -83,15 +85,15 @@
                    />
           </td>
-          <td width="78%" tal:content="row/title"></td>
+          <td width="66%" tal:content="row/title"></td>
           <td align="center" width="10%" tal:content="row/code"></td>
           <td align="center" width="2%">S<span tal:content="row/semester" /></td>
           <td align="center" width="2%" tal:content="row/credits"></td>
-          <td align="center" width="8%" tal:content="row/coe|nothing"></td>
-          
-          
-
-
-          <td>
-          <a tal:condition="python:review_state == 'school_fee_paid'" href="edit" tal:attributes="href string:${row/code}/course_edit_form"
+          <td align="center" width="10%" tal:content="row/coe|nothing"></td>
+          
+          
+
+
+          <td tal:condition="python:review_state == 'school_fee_paid'" width="5%" align="center">
+          <a href="edit" tal:attributes="href string:course_edit/${row/code}"
           target="edit"
           onclick="javascript:window.open('','edit','width=600, height=350, directories=no, toolbar=no, location=no, menubar=no, scrollbars=yes, status=no, resizable=no, dependent=no')">
