# coding: utf-8 ''' Created on 21.10.2016 @author: d.gulyakin ''' import json import string from java.io import ByteArrayOutputStream,\ FileNotFoundException, IOException, ByteArrayInputStream, StringBufferInputStream,\ FileInputStream from javax.xml.parsers import ParserConfigurationException from org.xml.sax import SAXException, InputSource from java.text import SimpleDateFormat from qt._qt_orm import QtiVariantAnswerCursor, QtiVariantCursor,\ QtiVariantQuestionCursor, QtiQuestionCursor, QtiThemeCursor,\ QtiVariantDestructorCursor, QtiVariantDestructorAnswerCursor,\ QtiDestructorCursor from common.numbersseries.getNextNo import getSeriesParams from umk._umk_orm import specialityCursor from nci._nci_orm import personCursor, test_matrixCursor try: from ru.curs.showcase.core.jython import JythonDTO, JythonDownloadResult, JythonErrorResult except: from ru.curs.celesta.showcase import JythonDTO, JythonDownloadResult, JythonErrorResult #XDocReport from fr.opensagres.xdocreport.template import TemplateEngineKind from fr.opensagres.xdocreport.document.registry import XDocReportRegistry from fr.opensagres.xdocreport.core import XDocReportException from freemarker.ext.dom import NodeModel from ru.curs.celesta.showcase.utils import XMLJSONConverter from ru.curs.showcase.core import UserMessageFactory from ru.curs.showcase.app.api.grid import GridSaveResult from common.sysfunctions import toHexForXml, getGridHeight from edu._edu_orm import educational_groupCursor, vw_edu_group_personsCursor,\ edu_group_personsCursor # from security.functions import userHasPermission _header = {"id": ["~~id"], "name": [u'Группа/Слушатель'], "login": [u'Имя пользователя'], "test": [u'Тестирование'], "time_begin": [u'Время начала'], "time_end": [u'Время окончания'], "time_finish": [u'Время завершения'], "testing_mark": [u'Оценка'], "score": [u'Процент правильных ответов'], "positive_count": [u'Количество правильных ответов'], "create_date": [u'Дата создания группы'], "HasChildren": [u'HasChildren'], 'properties': [u'properties']} _statuses = { 0: u'Начать тестирование', 30: u'Завершить тестирование', 31: u'Тестирование завершено'} def getTreeData(context, main, add, filterinfo, session, elementId, sortColumnList, firstrecord, pagesize, parentId=None): u'''Функция получения данных для tree-грида. ''' for column in _header: _header[column].append(toHexForXml(_header[column][0])) data = {"records":{"rec":[]}} speciality = main if parentId is None: groupsCur = educational_groupCursor(context) groupsCur.setRange('speciality', speciality) # Проходят обучение groupsCur.orderBy('control_date DESC', 'group_name') persons = edu_group_personsCursor(context) for group in groupsCur.iterate(): row = {} row[_header["id"][1]] = group.group_id # row[_header["name"][1]] = u'{}. {}'.format(group.group_id, group.group_name) row[_header["name"][1]] = string.join(filter(None, [group.group_name, group.kafedra_name, group.stud_spec_name, group.edu_level_name]), ', ') row[_header["create_date"][1]] = SimpleDateFormat("dd.MM.yyyy").format(group.create_date) status = group.status status_name = _statuses[group.status] if status==0: persons.setRange('group_id', group.group_id) if persons.count() > 0: row[_header["test"][1]] = {'div':{'ins':{'font':{"@style": "cursor: pointer !important", '@color': 'blue', '@title': status_name, '#text': status_name}}}} row[_header['properties'][1]] = {'event': { '@name': 'cell_single_click', '@column': _header['test'][0], 'action': { '@show_in': 'MODAL_WINDOW', '#sorted': [ {'main_context': 'current'}, {'modalwindow': { '@caption': group.group_name, '@height': '390', '@width': '640'}}, {'datapanel': { '@type': 'current', '@tab': 'current', 'element': { '@id': 'startTestCard', 'add_context': group.group_id}}}]}}} else: row[_header["test"][1]] = {'div':{'ins':{'font':{"@style": "cursor: pointer !important", '@color': 'blue', '@title': u'Добавить слушателей в группу для проведения тестирования', '#text': u'Добавить слушателей'}}}} row[_header['properties'][1]] = {'event': { '@name': 'cell_single_click', '@column': _header['test'][0], 'action': { '@show_in': 'MODAL_WINDOW', '#sorted': [ {'main_context': 'current'}, {'modalwindow': { '@caption': u'{}. Добавление слушателей'.format(group.group_name), '@height': '600', '@width': '980'}}, {'datapanel': { '@type': 'current', '@tab': 'current', 'element': { '@id': 'addTestGroupPersonsCard', 'add_context': group.group_id}}}]}}} elif status==30: # Кнопка для завершения тестирования row[_header["test"][1]] = {'div':{'ins':{'font':{"@style": "cursor: pointer !important", '@color': 'blue', '@title': status_name, '#text': status_name}}}} row[_header['properties'][1]] = {'event': { '@name': 'cell_single_click', '@column': _header['test'][0], 'action': { '@show_in': 'MODAL_WINDOW', '#sorted': [ {'main_context': 'current'}, {'modalwindow': { '@caption': group.group_name, '@height': '120', '@width': '600'}}, {'datapanel': { '@type': 'current', '@tab': 'current', 'element': { '@id': 'endTestCard', 'add_context': group.group_id}}}]}}} elif status == 31: row[_header["testing_mark"][1]] = {'span': {'#text': u'Результаты', '@style': 'padding: 2px 5px 0 0;'}} row[_header["test"][1]] = status_name else: row[_header["test"][1]] = status_name data["records"]["rec"].append(row) groupsCur.close() persons.close() else: _params = getSeriesParams(context, 'persons') prefix = _params['prefix'] postfix = _params['postfix'] dateFormat = SimpleDateFormat("dd.MM.yyyy HH:mm") group_personsCur = vw_edu_group_personsCursor(context) group_personsCur.setRange('group_id', parentId) group_personsCur.orderBy('surname', 'name', 'patronymic') variantAnsverCur = QtiVariantAnswerCursor(context) variantCur = QtiVariantCursor(context) for person in group_personsCur.iterate(): person_id = person.person_id row = {} row[_header["id"][1]] = "{}.{}".format(person.group_person_id, person_id) row[_header["name"][1]] = u'{} {} {}'.format(person.surname, person.name, person.patronymic) row[_header["login"][1]] = person_id.replace(prefix, '').replace(postfix, '') variantAnsverCur.setRange('VariantID', person.variant_id) if variantAnsverCur.tryFirst(): if variantCur.tryGet(variantAnsverCur.VariantID): row[_header["test"][1]] = variantCur.VariantName time_begin = variantAnsverCur.TimeBegin time_end = variantAnsverCur.TimeEnd time_finish = variantAnsverCur.TimeFinish row[_header["time_begin"][1]] = dateFormat.format(time_begin) if time_begin else None row[_header["time_end"][1]] = dateFormat.format(time_end) if time_end else None row[_header["time_finish"][1]] = dateFormat.format(time_finish) if time_finish else None row[_header["testing_mark"][1]] = {'span': {'#text': variantAnsverCur.TestingMark, '@style': 'padding: 2px 5px 0 0;'}} row[_header["score"][1]] = variantAnsverCur.Score row[_header["positive_count"][1]] = {'span': {'#text': variantAnsverCur.PositiveCount, '@style': 'padding: 2px 5px 0 0;'}} row[_header["HasChildren"][1]] = False # row[_header['properties'][1]] = {'event': {}} data["records"]["rec"].append(row) group_personsCur.close() variantAnsverCur.close() res = XMLJSONConverter.jsonToXml(json.dumps(data)) return JythonDTO(res, None) def getTreeSettings(context, main, add, filterinfo, session, elementId): u'''Функция получения настроек для tree-грида. ''' panelWidth = '100%' panelHeight = getGridHeight(session, numberOfGrids = 1, delta=65) # speciality = main # groupsCur = educational_groupCursor(context) # groupsCur.setRange('speciality', speciality) # Проходят обучение # totalCount = studentCur.count() totalCount = 0 # groupsCur.close() # Определяем список полей таблицы для отображения settings = {} settings["gridsettings"] = { # "labels": {'header': u'ЭОР по теме'}, "columns": {"col":[ {"@id":_header["name"][0], "@width":"240px"}, # {"@id":_header["login"][0], "@width":"100px", "@horAlign": 'CENTER'}, {"@id":_header["test"][0], "@width":"100px", "@horAlign": 'CENTER'}, {"@id":_header["testing_mark"][0], "@width":"70px", "@horAlign": 'CENTER', "@type":"DOWNLOAD", "@linkId":"downloadStudentFile"}, {"@id":_header["time_begin"][0], "@width":"80px", "@horAlign": 'CENTER'}, {"@id":_header["time_end"][0], "@width":"80px", "@horAlign": 'CENTER'}, {"@id":_header["time_finish"][0], "@width":"80px", "@horAlign": 'CENTER'}, {"@id":_header["score"][0], "@width":"60px", "@horAlign": 'CENTER'}, {"@id":_header["positive_count"][0], "@width":"60px", "@horAlign": 'CENTER', "@type":"DOWNLOAD", "@linkId":"downloadStudentAppealFile"}, {"@id":_header["create_date"][0], "@width":"80px", "@horAlign": 'CENTER'} ]}, "properties": { "@gridHeight": panelHeight, "@gridWidth": panelWidth, "@pagesize": "25", "@totalCount": totalCount}} res_set = XMLJSONConverter.jsonToXml(json.dumps(settings)) return JythonDTO(None, res_set) def gridToolBar(context, main=None, add=None, filterinfo=None, session=None, elementId=None): try: row = json.loads(session)['sessioncontext']['related']['gridContext']["currentRecordId"] except: row = None status_id = -1 group_name = u'' if row: groupsCur = educational_groupCursor(context) if groupsCur.tryGet(row): status_id = groupsCur.status group_name = groupsCur.group_name grid_toolbar = { 'gridtoolbar': { '#sorted': [ {'item': { '@text': u'Импорт групп', '@hint': u'Импорт групп тестирования', '@disable': 'false', 'action': { '@show_in': 'MODAL_WINDOW', '#sorted': [ {'main_context': 'current'}, {'modalwindow': { '@caption': u'Импорт групп тестирования', "@height":"200", "@width":"460"}}, {'datapanel': { '@type': 'current', '@tab': 'current', 'element': { '@id': 'importTestGroupsCard', 'add_context': row}}}]}}}, {'item': { '@text': u'Добавить группу', '@hint': u'Добавление группы тестирования', '@disable': 'false', 'action': { '@show_in': 'MODAL_WINDOW', '#sorted': [ {'main_context': 'current'}, {'modalwindow': { '@caption': u'Добавление группы тестирования', "@height":"400", "@width":"460"}}, {'datapanel': { '@type': 'current', '@tab': 'current', 'element': { '@id': 'addTestGroupCard', 'add_context': row}}}]}}}, {'item': { '@text': u'Добавить слушателей', '@hint': u'Добавление слушателей в группу для проведения тестирования', '@disable': 'false' if status_id == 0 else 'true', 'action': { '@show_in': 'MODAL_WINDOW', '#sorted': [ {'main_context': 'current'}, {'modalwindow': { '@caption': u'{}. Добавление слушателей'.format(group_name), "@height":"600", "@width":"980"}}, {'datapanel': { '@type': 'current', '@tab': 'current', 'element': { '@id': 'addTestGroupPersonsCard', 'add_context': row}}}]}}}]}} return XMLJSONConverter.jsonToXml(json.dumps(grid_toolbar)) def downloadStudentAppealFile(context, main=None, add=None, filterinfo=None, session=None, elementId=None, recordId=None): u'''процедура получения файла апелляции''' grainPath = context.grain.getGrainPath().toString() try: template = FileInputStream(grainPath + '/template/appeal.docx') if template: data = getStudentAppealData(context, main, recordId) dataXML = XMLJSONConverter.jsonToXml(json.dumps(data)).encode("utf-8") fileName = u'Апелляция-{}-{}.docx'.format(data['student']['group'], data['student']['fio']).replace(':', '_').replace(',', '_').replace(' ', '_') # result = open(grainPath + '/template/dataOut.xml', 'rb+') # try: # result.write(dataXML) # finally: # result.close() report = XDocReportRegistry.getRegistry().loadReport(template, TemplateEngineKind.Freemarker) reportContext = report.createContext() projectInputStream = StringBufferInputStream(dataXML) projectInputSource = InputSource(projectInputStream) project = NodeModel.parse(projectInputSource) reportContext.put("doc", project) out = ByteArrayOutputStream() report.process(reportContext, out) bytesOut = out.toByteArray() out.close() return JythonDownloadResult(ByteArrayInputStream(bytesOut), fileName) else: return context.error(u"Шаблон отсутствует") except FileNotFoundException as err: return context.error(u"Ошибка: %s" % format(err)) except IOException as err: return context.error(u"Ошибка: %s" % format(err)) except XDocReportException as err: return context.error(u"Ошибка: %s" % format(err)) except ParserConfigurationException as err: return context.error(u"Ошибка: %s" % format(err)) except SAXException as err: return context.error(u"Ошибка: %s" % format(err)) def getStudentAppealData(context, speciality_id, recordId): speciality_name = u'' fio = u'' group_name = u'' testing_date = '' testing_time_start = '00:00' testing_time_end = '00:00' testing_score = '' test_config_id = '' test_config_name = u'' correct_questions = 0 all_questions = 0 letters = [u'А',u'Б',u'В',u'Г',u'Д',u'Е',u'Ж',u'З',u'И',u'К'] row = recordId.split('.') group_person_id = row[0] person_id = row[1] specialityCur = specialityCursor(context) if specialityCur.tryGet(speciality_id): speciality_name = specialityCur.name specialityCur.close() personCur = personCursor(context) if personCur.tryGet(person_id): fio = personCur.fullname personCur.close() variant_id = None group_id = None group_personsCur = edu_group_personsCursor(context) if group_personsCur.tryGet(group_person_id): variant_id = group_personsCur.variant_id group_id = group_personsCur.group_id group_personsCur.close() if group_id: groupCur = educational_groupCursor(context) if groupCur.tryGet(group_id): group_name = groupCur.group_name test_config_id = groupCur.package_id groupCur.close() test_matrixCur = test_matrixCursor(context) if test_matrixCur.tryGet(test_config_id): test_config_name = test_matrixCur.tm_name test_matrixCur.close() questions = {'row': []} if variant_id: variant_answerCur = QtiVariantAnswerCursor(context) variant_answerCur.setRange('VariantID', variant_id) if variant_answerCur.tryFirst(): testing_date = SimpleDateFormat("dd.MM.yyyy HH:mm").format(variant_answerCur.TimeBegin) if variant_answerCur.TimeBegin else '' testing_time_start = SimpleDateFormat("HH:mm").format(variant_answerCur.TimeBegin) if variant_answerCur.TimeBegin else '00:00' testing_time_end = SimpleDateFormat("HH:mm").format(variant_answerCur.TimeEnd) if variant_answerCur.TimeEnd else'00:00' testing_score = variant_answerCur.Score variant_answerCur.close() variant_questionCur = QtiVariantQuestionCursor(context) variant_questionCur.setRange('VariantID', variant_id) variant_questionCur.orderBy('QuestionNumber') questionCur = QtiQuestionCursor(context) all_questions = variant_questionCur.count() QtiVariantDestructor = QtiVariantDestructorCursor(context) QtiVariantDestructorAnswer = QtiVariantDestructorAnswerCursor(context) QtiDestructor = QtiDestructorCursor(context) for variant_questionCur in variant_questionCur.iterate(): allAnswers = [] question_text = u'' answer = [] allAnswers = [] if questionCur.tryGet(variant_questionCur.QuestionID): question_text = questionCur.QuestionHtml if questionCur.QuestionHtml is not None else '' if variant_questionCur.QuestionType == 1: letter = 0 QtiVariantDestructor.setRange('VariantQuestionID', variant_questionCur.VariantQuestionID) QtiVariantDestructor.orderBy('VariantDestructorID') for QtiVariantDestructor in QtiVariantDestructor.iterate(): QtiVariantDestructorAnswer.setRange('VariantDestructorID', QtiVariantDestructor.VariantDestructorID) if QtiDestructor.tryGet(QtiVariantDestructor.DestructorID): allAnswers.append({'answer_letter': letters[letter], 'answer_text': QtiDestructor.DestructorHtml, 'isTrue': QtiDestructor.IsTrue}) if QtiVariantDestructorAnswer.tryFirst(): answer.append({'answer_letter': letters[letter], 'answer_text':QtiDestructor.DestructorHtml}) letter += 1 if variant_questionCur.CorrectAnswer: correct = u'Да' correct_questions += 1 else: correct = u'Нет' questions['row'].append({'number': variant_questionCur.QuestionNumber, 'question_text': question_text, 'answer': answer, 'correct': correct, 'allAnswers': allAnswers}) QtiVariantDestructor.close() QtiVariantDestructorAnswer.close() QtiDestructor.close() questionCur.close() variant_questionCur.close() data = {'student': { 'fio': fio, 'speciality': speciality_name, 'group': group_name, 'testing_date': testing_date, 'testing_time': '{} - {}'.format(testing_time_start, testing_time_end), 'testing_score': testing_score, 'test_config_name': test_config_name, 'correct_questions': correct_questions, 'all_questions': all_questions, 'questions': questions}} return data def downloadStudentFile(context, main=None, add=None, filterinfo=None, session=None, elementId=None, recordId=None): u'''процедура получения файлов''' grainPath = context.grain.getGrainPath().toString() try: is_group = recordId.find('.') if is_group == -1: template = FileInputStream(grainPath + '/template/protocolGroup.docx') data = getStudentsGroupData(context, main, recordId) fileName = u'{}.docx'.format(data['group']['name']).replace(':', '_').replace(',', '_').replace(' ', '_') else: template = FileInputStream(grainPath + '/template/protocol.docx') data = getStudentData(context, main, recordId) fileName = u'{}-{}.docx'.format(data['student']['group'], data['student']['fio']).replace(':', '_').replace(',', '_').replace(' ', '_') if template: dataXML = XMLJSONConverter.jsonToXml(json.dumps(data)).encode("utf-8") # result = open(grainPath + '/template/dataOut.xml', 'rb+') # try: # result.write(dataXML) # finally: # result.close() report = XDocReportRegistry.getRegistry().loadReport(template, TemplateEngineKind.Freemarker) reportContext = report.createContext() projectInputStream = StringBufferInputStream(dataXML) projectInputSource = InputSource(projectInputStream) project = NodeModel.parse(projectInputSource) reportContext.put("doc", project) out = ByteArrayOutputStream() report.process(reportContext, out) bytesOut = out.toByteArray() out.close() return JythonDownloadResult(ByteArrayInputStream(bytesOut), fileName) else: return context.error(u"Шаблон отсутствует") except FileNotFoundException as err: return context.error(u"Ошибка: %s" % format(err)) except IOException as err: return context.error(u"Ошибка: %s" % format(err)) except XDocReportException as err: return context.error(u"Ошибка: %s" % format(err)) except ParserConfigurationException as err: return context.error(u"Ошибка: %s" % format(err)) except SAXException as err: return context.error(u"Ошибка: %s" % format(err)) def getStudentsGroupData(context, speciality_id, recordId): group_id = recordId group_name = u'' groupCur = educational_groupCursor(context) if groupCur.tryGet(group_id): group_name = groupCur.group_name groupCur.close() group_personsCur = vw_edu_group_personsCursor(context) group_personsCur.setRange('group_id', group_id) group_personsCur.orderBy('surname', 'name', 'patronymic') group_data = {'group': { 'name': group_name, 'scount': 0, 'students': []}} i = 0 for person in group_personsCur.iterate(): i += 1 row_id = "{}.{}".format(person.group_person_id, person.person_id) student_data = getStudentData(context, speciality_id, row_id) student_data['student']['index'] = i group_data['group']['students'].append(student_data['student']) group_data['group']['scount'] = i return group_data def getStudentData(context, speciality_id, recordId): speciality_name = u'' fio = u'' group_name = u'' testing_date = '' testing_date_by_group = '' testing_time_start = '00:00' testing_time_end = '00:00' testing_score = '0' edu_level_name = '' stud_spec_name = '' kafedra_name = '' positive_count = '0' mark = 'неудовлетворительно' params = None row = recordId.split('.') group_person_id = row[0] person_id = row[1] specialityCur = specialityCursor(context) if specialityCur.tryGet(speciality_id): speciality_name = specialityCur.name specialityCur.close() personCur = personCursor(context) if personCur.tryGet(person_id): fio = personCur.fullname personCur.close() variant_id = None group_id = None group_personsCur = edu_group_personsCursor(context) if group_personsCur.tryGet(group_person_id): variant_id = group_personsCur.variant_id group_id = group_personsCur.group_id group_personsCur.close() if group_id: groupCur = educational_groupCursor(context) if groupCur.tryGet(group_id): group_name = groupCur.group_name kafedra_name = groupCur.kafedra_name stud_spec_name = groupCur.stud_spec_name edu_level_name = groupCur.edu_level_name params = json.loads(groupCur.params) testing_date_by_group = SimpleDateFormat("dd.MM.yyyy").format(groupCur.control_date) groupCur.close() questions = {'row': []} if variant_id: variant_answerCur = QtiVariantAnswerCursor(context) variant_answerCur.setRange('VariantID', variant_id) if variant_answerCur.tryFirst(): testing_date = SimpleDateFormat("dd.MM.yyyy").format(variant_answerCur.TimeBegin) if variant_answerCur.TimeBegin else '' testing_time_start = SimpleDateFormat("HH:mm").format(variant_answerCur.TimeBegin) if variant_answerCur.TimeBegin else '00:00' testing_time_end = SimpleDateFormat("HH:mm").format(variant_answerCur.TimeEnd) if variant_answerCur.TimeEnd else'00:00' testing_score = variant_answerCur.Score positive_count = variant_answerCur.PositiveCount variant_answerCur.close() variant_questionCur = QtiVariantQuestionCursor(context) variant_questionCur.setRange('VariantID', variant_id) variant_questionCur.orderBy('QuestionNumber') questionCur = QtiQuestionCursor(context) themeCur = QtiThemeCursor(context) row = {'question': []} num = 0 for variant_questionCur in variant_questionCur.iterate(): theme_num = '' question_num = '' if questionCur.tryGet(variant_questionCur.QuestionID): question_num = str(questionCur.QuestionOrder).zfill(4) theme_id = questionCur.ThemeID if themeCur.tryGet(theme_id): theme_num = str(themeCur.ThemeOrder).zfill(2) answer = '+' if variant_questionCur.CorrectAnswer else '-' if theme_num and question_num: answer = '{}.{} {}'.format(theme_num, question_num, answer) number = variant_questionCur.QuestionNumber row_num = (number - 1) // 4 if row_num <> num: num = row_num questions['row'].append(row) row = {'question': []} row['question'].append({'number': '{}.'.format(number), 'answer': answer}) if row['question']: questions['row'].append(row) themeCur.close() questionCur.close() variant_questionCur.close() if params != None: mark3 = params['Percent3'] mark4 = params['Percent4'] mark5 = params['Percent5'] if testing_score >= mark5: mark = 'отлично' elif testing_score >= mark4: mark = 'хорошо' elif testing_score >= mark3: mark = 'удовлетворительно' else: mark = 'неудовлетворительно' if testing_score != None: if testing_score>=90: mark = 'отлично' elif testing_score >= 80: mark = 'хорошо' elif testing_score >= 70: mark = 'удовлетворительно' else: mark = 'неудовлетворительно' if (testing_date == None or testing_date == ''): testing_date = testing_date_by_group data = {'student': { 'fio': fio, 'speciality': speciality_name, 'group': group_name, 'kafedra_name': kafedra_name, 'stud_spec_name': stud_spec_name, 'edu_level_name': edu_level_name, 'testing_date': testing_date, 'testing_time': '{} - {}'.format(testing_time_start, testing_time_end), 'testing_score': testing_score, 'positive_count': positive_count, 'mark': mark, 'total_count': len(questions['row']), 'questions': questions}} return data # def gridPartialUpdate(context, main, add, filterinfo, session, elementId, sortColumnList, firstrecord, pagesize, parentId=None): # u"""Частичное обновление грида""" # data = {"records":{"rec":[]}} # # if add: # row = add.split('.') # row_type = row[0] # row_id = row[1] # if row_type == 'task': # eor_tasksCursor = student_eor_tasksCursor(context) # if eor_tasksCursor.tryGet(row_id): # type = eor_tasksCursor.eor_type # id = "task.{}".format(eor_tasksCursor.task_id) # row = {} # row[_header["id"][1]] = id # row[_header["name"][1]] = eor_tasksCursor.package_name # row[_header["eor_type"][1]] = EOR_TYPE[type][0] # row[_header["score"][1]] = eor_tasksCursor.score # if type == TEST: # row[_header["attempts_count"][1]] = eor_tasksCursor.attempts_count # row[_header["HasChildren"][1]] = 0 # row[_header['properties'][1]] = {'event': { # '@name': 'row_save_data', # 'action': { # '#sorted': [ # {'main_context': 'current'}, # {'datapanel': { # '@type': 'current', # '@tab': 'current', # "element": [ # {"@id": "studentsTreeGrid", # "@keep_user_settings": "true", # "@partial_update": "true", # "add_context": id}]}}]}}} # data["records"]["rec"].append(row) # # eor_tasksCursor.close() # # res = XMLJSONConverter.jsonToXml(json.dumps(data)) # return JythonDTO(res, None)