Esempio n. 1
0
 def Load(self):
     f = None
     try:
         f = open(self.source)
         self.txt = f.read()
         f.close()
     except:
         if f:
             f.close()
         LogLastError(u'Exception in Open ...')
Esempio n. 2
0
 def Save(self):
     f = None
     try:
         f = open(self.source, 'wb')
         f.write(str({'description': self.description, 'data': self.data}))
         f.close()
     except:
         if f:
             f.close()
         LogLastError(u'Exception in Update ...', self.logType)
         raise Exception
Esempio n. 3
0
def getReplDict(typSprav, fieldKey, fieldVal, exprSelect=None):
    """
    Функция формируем словарь соответствий по справочнику.

    @type typSpr: C{string}
    @param typSpr: Тип справочника.
    @type fieldKey: C{string}
    @param fieldKey: Поле, которое будет выступать в качестве ключа.
    @type fieldVal: C{string}
    @param filedVal: Поле, которое будет выступать в качестве значения.
    @type exprSelect: C{<function>}
    @param exprSelect: Выражения фильтации.
    @rtype: C{dictionary}
    @return: Cловарь соответствий между полями справочника.
    """
    dict = {}

    try:
        #   Определяем имя класса данных справочника
        #   Создаем класс данных типов справочников
        _NsiList = tabclass.CreateTabClass(getNsiListClassName())

        #   Находим описание нужного справочника
        rs = _NsiList.select(_NsiList.q.type == typSprav)

        #if len(rs) == 0:
        if GetRecordCount(rs) == 0:
            print('Invalid sprav type')
            return None

        spr = rs[0]

        #   Создаем классы данных справочника и изменяемых во времени параметров
        _Sprav = tabclass.CreateTabClass(spr.tab)
        cnList = _NsiList._connection.getConnection()
        cnSprav = _Sprav._connection.getConnection()

        if exprSelect:
            rs = _Sprav.select(exprSelect)
        else:
            rs = _Sprav.select(_Sprav.q.id_nsi_listID == spr.id)

        for r in rs:
            key = getattr(r, fieldKey)
            value = getattr(r, fieldVal)
            dict[key] = value

        cnList.commit()
        cnSprav.commit()
    except:
        LogLastError('>>> Error in getReplDict')
        dict = None

    return dict
Esempio n. 4
0
def NsiEdtFormName(typSprav, level_num=1):
    """
    Определяет название формы редактирования справочника.
    
    @type typSprav: C{string}
    @param typSprav: Тип справочника.
    @type level_num: C{int}
    @param level_num: Номер уровня кода справочника.
    @rtype: C{string}
    @return: Возвращает имя формы для редактирования справочника. None - в случае
        если тип справочника не определен.
    """

    #   Создаем класс данных типов справочников
    _NsiList = tabclass.CreateTabClass(getNsiListClassName())
    _NsiLevel = tabclass.CreateTabClass(getNsiLevelClassName())
    cnList = _NsiList._connection.getConnection()
    cnLevel = _NsiLevel._connection.getConnection()

    result = NSI_STD_EDIT_FORM

    try:
        #   Находим описание нужного справочника
        rs = _NsiList.select(_NsiList.q.type == typSprav)

        #if len(rs) == 0:
        if GetRecordCount(rs) == 0:
            print('Invalid sprav type')
            return None

        obj = rs[0]

        #   Если не указано количество уровней кода, то считаем, что структура кода
        #   одноуровневая, код представляется тексовым полем и используются стандартные
        #   формы для редактирования и выбора.
        if int(obj.level_num) <= 0:
            return result

        rs_lev = _NsiLevel.select(_NsiLevel.q.id_nsi_listID == obj.id)

        for lev in rs_lev:
            if str(lev.level) == str(level_num):
                result = lev.edit_form_id
                print('find edit form name (NsiEdtFormName) :', result)
                break
    except:
        LogLastError('ERROR in NsiEdtFormName')

    cnList.commit()
    cnLevel.commit()

    return result
Esempio n. 5
0
    def addRecord(self, values=None, postAddExpr=None, uuid_postAddExpr=None):
        """
        Функция добавляет новую запись.

        @param fieldName: Имя колонки.
        @type fieldName: C{string}
        @type values: C{dictionary}
        @param values: Словарь известных значений. В качестве ключей имена полей,
            значения полей в качестве значений.
        @type postAddExpr: C{string}
        @param postAddExpr: Параметр совместимости с icSQLObjDataSet.
        @type uuid_postAddExpr: C{string}
        @return uuid_postAddExpr: Параметр совместимости с icSQLObjDataSet.
        @return: Возвращает признак успешного выполнения.
        @rtype: C{bool}
        """
        #   Проверка на права доступа к данному методу
        if not icuser.canAuthent('a', self.name, icuser.ACC_DATA, True):
            return False

        rec = self.getRecordCount()

        if values is None and self.changeRowBuff is not None and rec in self.changeRowBuff:
            values = self.changeRowBuff[rec]

        try:
            lst = self.getFieldList()
            row_lst = range(len(lst))

            for indx, fld in enumerate(lst):
                if values and fld in values:
                    row_lst[indx] = values[fld]
                elif self.init and fld in self.init:
                    row_lst[indx] = self.init[fld]
                else:
                    row_lst[indx] = None

            value = self.data.append(row_lst)
            self._is_changed = True
            if self.allChangeBuff:
                self.allChangeBuff.reg_add(row_lst)

            #   Переводим курсор на последнюю запись
            self.Move(-1)
            #   Чистим буфер введенной записи
            self.clearChangeRowBuff(rec)
        except:
            LogLastError(u'addRecord ERROR')

        return True
Esempio n. 6
0
    def FindRowString(self, string, cursor=-1, fields=None, bILike=True):
        """
        Функция ищет подстроку в массиве данных.
        Это желательная функция для всех объектов данных, используется
        в для поиска в объекте навигации.

        @type string: C{string}
        @param string: Строка поиска
        @type cursor: C{int}
        @param cursor: Начальное положение курсора.
        @type fields: C{list}
        @param fields: Список полей по которым ведется поиск.
        @type bILike: C{bool}
        @param bILike: Признак поиска без учета регистра. Если False - то поиск ведется
            на точное соответствие.
        @rtype: C{tuple}
        @return: Возвращает номер строку и название поля, где найдена искомая строка.
        """
        try:
            # Без учета регистра?
            if bILike:
                string = string.upper()
            # Начальное положение курсора
            if cursor < 0:
                cursor = 0
            # Имена полей
            if fields is None:
                fields = self.getFieldList()

            # Перебор строк
            for i_row in range(cursor, len(self.data)):
                # Перебор полей
                for field in fields:
                    # Получить значение поля
                    if bILike:
                        value = self.getNameValue(field, i_row).upper()
                    else:
                        value = self.getNameValue(field, i_row)
                    # Проверка на совпадение подстроки
                    if string in value:
                        return i_row, field

            return -1, None
        except:
            LogLastError()
            # Подстрока не найдена
            return -1, None
Esempio n. 7
0
def getSpravDictSimple(typSprav):
    """
    Получить справочник заданного типа в виде словаря.
    @type typeSprav: C{...}
    @param typeSprav: Тип справочника.
    @return: Возвращает словарь следующей структуры:
        {
        'COD1':{'cod':'COD1','name':'name1','s1':'',...},
        .
        .
        .
        'COD_N':{'cod':'COD_N','name':'name_N','s1':'',...},
        }
    """
    try:
        #   Определяем имя класса данных справочника
        #   Создаем класс данных типов справочников
        _NsiList = tabclass.CreateTabClass(getNsiListClassName())

        #   Находим описание нужного справочника
        rs = _NsiList.select(_NsiList.q.type == typSprav)

        if GetRecordCount(rs) == 0:
            print('Invalid sprav type')
            return None

        spr = rs[0]

        #   Создаем классы данных справочника и изменяемых во времени параметров
        _Sprav = tabclass.CreateTabClass(spr.tab)
        cnList = _NsiList._connection.getConnection()
        cnSprav = _Sprav._connection.getConnection()

        rs = _Sprav.select(_Sprav.q.id_nsi_listID == spr.id)

        sprav_dict = {}
        if GetRecordCount(rs):
            #sprav_dict=dict(map(lambda r: (r.cod,dict(r)),rs))
            for r in rs:
                sprav_dict[r.cod] = GetRecordDict(r)

        cnList.commit()
        cnSprav.commit()
    except:
        LogLastError('>>> Error in getSpravDictSimple')
        sprav_dict = None
    return sprav_dict
Esempio n. 8
0
def isSimbEqTemplate(keycod, ins_pos, text, templ):
    """
    Проверяет соответствует ли шаблону вводимый символ
    @return: Возвращает признак соответствия вводимого символа шаблону
    @rtype: C{true | false}
    @param keycod: Код (wxPython) нажатой клавиши.
    @type keycod: C{int}
    @param ins_pos: Позиция курсора
    @type ins_pos: C{int}
    @param text: Текст
    @type text: C{string}
    @param templ: Шаблон вывода
    @type templ: C{string}
    """
    ret = 0
    oldTxt = text
    if keycod > 256:
        return False
    try:
        #   Получаем текст, который получится после ввода символа
        txt = text[:ins_pos] + chr(keycod) + text[ins_pos:]
        #   Сравниваем c шаблоном
        for i in range(len(txt)):
            ch = txt[i]
            cht = templ[i]
            #   Проверяем на разделители шаблонов
            for div in ListDIV:
                if cht == div and i + 1 < len(templ):
                    cht = templ[i + 1]
            if cht == u'X':
                ret = True
            elif 48 <= ord(cht) <= 57:
                ret = (ord(ch) == 45 or (48 <= ord(ch) <= ord(cht)))
            else:
                ret = (cht == ch)
            if ret == 0:
                return False
        ret = True
    #   Если шаблон не определен, то считаем, что ввод правильный
    except:
        LogLastError(u'Exception')
        ret = True

    return ret
Esempio n. 9
0
    def update(self, values=None, rec=None, bReal=False, bCtrl=True):
        """
        Устанавливает значения полей заданной строки. Если имя поля не найдено
        в источнике данных, то функция пытается выполнить функцию на запись по
        описанию колонки из ресурсного описания по аттрибуту 'setvalue'. Если
        словарь обновлений (values) не определен, то обновления берутся из
        буфера изменений строки.

        @type rec: C{int}
        @param rec: Номер записи.
        @type values: C{dictionary}
        @param values: Словарь значений. В качестве ключей используются имена полей.
        @type bReal: C{bool}
        @param bReal: Параметр совместимости с icSQLObjDataSet.
        @type bCtrl: C{bool}
        @param bCtrl: Параметр совместимости с icSQLObjDataSet.
        @return: Возвращает код контроля записи = IC_CTRL_OK.
        """
        #   Если номер строки не указан, то номер записи определяем по положению курсора
        if rec is None:
            rec = self.cursor

        #   Берем значения из буфера изменений. В этом случае контроль поля
        #   проводить уже не надо

        if values is None and self.changeRowBuff is not None and rec in self.changeRowBuff:
            values = self.changeRowBuff[rec]

        if isinstance(values, dict):
            try:
                for fld, val in values.items():
                    indxFld = self.getFieldList().index(fld)
                    self.data[rec][indxFld] = val

                self._is_changed = True
                if self.allChangeBuff:
                    self.allChangeBuff.reg_update(self.data[rec])
            except:
                LogLastError(u'update ERROR')

            #   Чистим буфер изменений данной строки
            self.clearChangeRowBuff(rec)

        return coderror.IC_CTRL_OK
Esempio n. 10
0
def getSpravLevel(Type_, Level_=1):
    """
    Получить записи справочника определенного уровня.
    @param Type_: Тип справочника.
    @param Level_: Запрашиваемый уровень.
    """
    try:
        #Получить информацию о справочнике
        _NsiList = tabclass.CreateTabClass(getNsiListClassName())
        #   Находим описание нужного справочника
        rs = _NsiList.select(_NsiList.q.type == Type_)

        if GetRecordCount(rs) == 0:
            print('Invalid sprav type')
            return None

        #Запись данных о справочнике
        spr = rs[0]

        cod_level_len = getLevelCodLen(Type_, Level_)

        nsi_std_name = spr.tab
        nsi_listID = spr.id
        #sql='''SELECT * FROM %s
        #    WHERE %s.id_nsi_list=%d AND
        #    LENGTH(%s.cod)=%d'''%(spr.tab,
        #    spr.tab,spr.id,spr.tab,cod_level_len)
        #Завершить транзакцию
        _NsiList._connection.getConnection().commit()

        _NsiStd = tabclass.CreateTabClass(nsi_std_name)
        nsi_std_name_db = mixedToUnder(nsi_std_name)
        rs = _NsiStd.select(
            '''%s.id_nsi_list_id=%d AND LENGTH(%s.cod)=%d''' %
            (nsi_std_name_db, nsi_listID, nsi_std_name_db, cod_level_len))
        #_NsiStd._connection.getConnection().commit()
        #print 'getSpravLevel',rs.count()
        return rs
    except:
        LogLastError('>>> Error in getSpravLevel')
        return None
Esempio n. 11
0
def newSprav(Type_, Cod_, Name_, **KWSprav_):
    """
    Создать новую запись в справочнике.
    """
    try:
        #   Создаем класс данных типов справочников
        _NsiStd = tabclass.CreateTabClass(getNsiStdClassName())
        nsi_listID = getSpravId(Type_)

        rec = _NsiStd(type=Type_,
                      id_nsi_list=nsi_listID,
                      cod=Cod_,
                      name=Name_,
                      count=0,
                      access='',
                      **KWSprav_)

        return rec
    except:
        LogLastError('>>> Error in newSprav')
        return None
Esempio n. 12
0
    def getNameValue(self, fieldName, rec=None, bReal=False, bFromBuff=True):
        """
        Функция по имени колонки и номеру записи возвращает значение
        из буфера.
        @type rec: C{int}
        @param rec: Номер строки.
        @type fieldName: C{string}
        @param fieldName: Имя поля.
        @type bReal: C{bool}
        @param bReal: Параметр совместимости с icSQLObjDataSet.
        @type bFromBuff: C{bool}
        @param bFromBuff: Параметр совместимости с icSQLObjDataSet.
        @rtype: C{...}
        @return: По имени колонки и номеру записи возвращает значение из буфера. Если поле или номер записи
            указаны не верно, то функция возвращает C{None}.
        """
        value = ''
        #   Проверка на права доступа к данному методу
        if not icuser.canAuthent('r', self.name, icuser.ACC_DATA, False):
            return ''
        #   Если номер строки не указан, то номер записи определяем по положению курсора
        if rec is None:
            rec = self.cursor
        #   Проверяем буфер изменений. Если там есть значение, то берем
        #   его из буфера.
        if bFromBuff and (self.changeRowBuff is not None
                          and rec in self.changeRowBuff
                          and fieldName in self.changeRowBuff[rec]):
            value = self.changeRowBuff[rec][fieldName]

        elif 0 <= rec < self.getRecordCount():
            #   Определяем индекс поля
            try:
                indxFld = self.getFieldList().index(fieldName)
                value = self.data[rec][indxFld]
            except:
                LogLastError(u'getNameValue ERROR')

        return value
Esempio n. 13
0
    def Reconstruct(self):
        """
        Переконструирует сайзер.
        """
        _list = self.objectList
        self.objectList = []
        
        for indx, obj in enumerate(_list):
            if not issubclass(obj.__class__, wx.Sizer):
                obj.size = obj.GetSize()
                self.Detach(obj)

        for indx, obj in enumerate(_list):
            if not issubclass(obj.__class__, wx.Sizer):
                if obj.size[0] == -1:
                    obj.SetSize((50, obj.size[1]))
                    
                obj.SetSize(obj.size)

                if obj.position == (-1, -1):
                    pos = (0, indx)
                else:
                    pos = obj.position

                try:
                    self.Add(obj, pos, obj.span, obj.flag, obj.border)
                    
                    if obj.span[0] == 1 and obj.span[1] == 1:
                        self.SetItemMinSize(obj, obj.size)
                    elif obj.flag != wx.EXPAND:
                        self.SetItemMinSize(obj, obj.size)
                except:
                    LogLastError('Reconstruct Error')
            else:
                self.objectList.append(obj)
                
        self.Layout()
Esempio n. 14
0
def HlpSprav(typSprav,
             ParentCode=(None, ),
             field=None,
             datatime=None,
             form=None,
             rec=None,
             parentForm=None):
    """
    Запуск визуального интерфейса просмотра,  поиска и выбора значений поля
        или группы полей из отмеченной строки указанного справочника.
    @type typSprav: C{string}
    @param typSprav: Код типа (номер) справочника.
    @type ParentCode: C{...}
    @param ParentCode: Код более верхнего уровня.
    @param field: Задает поле или группу полей, которые надо вернуть.
    @type datatime: C{string}
    @param datatime: Время актуальности кода.
    @param form: имя формы визуального интерфейса работы со справочником.
    @param rec: Текущая запись справочника.
    @param parentForm: Родительская форма.
    """
    result = IC_HLP_OK
    res_val = None

    print('Start HlpSprav FIELD:', field)
    try:
        if ParentCode is None:
            ParentCode = (None, )

        #Для обработки необходимо преобразовать в список
        parent_code = list(ParentCode)
        #Запрашиваемый уровень
        try:
            x_level = parent_code.index(None)
            parent_code_str = ''.join(parent_code[:x_level])
            x_level += 1
            print('HlpSprav Level:', x_level)
        except:
            x_level = None
            #Весь код заполнен
            res_val = (ParentCode, get_fields(field, rec))
            str_code = get_hlp_code_str(typSprav, ParentCode)
            print('HlpSprav Resultation: ', field, rec, res_val, str_code)
            return (result, res_val[0], res_val[1], str_code)

        #Получить информацию о справочнике
        _NsiList = tabclass.CreateTabClass(getNsiListClassName())

        #   Находим описание нужного справочника
        rs = _NsiList.select(_NsiList.q.type == typSprav)

        #if len(rs) == 0:
        if GetRecordCount(rs) == 0:
            print('Invalid sprav type')
            return (IC_HLP_FAILED_TYPE_SPRAV, res_val)

        spr = rs[0]

        #Если запрашиваемый уровень больше общего количества уровней, то выйти
        #Нет такого уровня в справочнике
        if spr.level_num < x_level:
            print('Invalid level %d' % (x_level))
            return (IC_HLP_FAILED_LEVEL, res_val)

        #определить длину кода уровня
        _NsiLevel = tabclass.CreateTabClass(getNsiLevelClassName())
        rs = _NsiLevel.select(_NsiLevel.q.type == typSprav)
        level_len = None
        for rec in rs:
            if rec.level == x_level:
                level_len = rec.level_len
                break

        if level_len is None:
            MsgBox(None, 'Не определена длина кода уровня!')
            return (IC_HLP_FAILED_LEVEL, res_val)

        parent_len = len(parent_code_str)

        result = IC_HLP_FAILED

        #--- Если указана дата актуальности ---
        if datatime:
            sprav_t = spr.tab + 'T'
            sql = '''SELECT id FROM %s
                WHERE SUBSTR(cod,1,%d) LIKE(\'%s\') AND
                LENGTH(SUBSTR(cod,%d,LENGTH(cod)-%d))=%d AND
                time_start<=%s AND time_end>=%s''' % (
                sprav_t, parent_len, parent_code_str, parent_len + 1,
                parent_len, level_len, str(datatime), str(datatime))

        #---  Если дата актуальности не указана либо в таблице актуальности нет инф.
        #   за нужный период, то проверяем по справочной таблице
        if not datatime:
            sql = '''SELECT id FROM %s
                WHERE %s.id_nsi_list=%d AND
                SUBSTR(%s.cod,1,%d) LIKE(\'%s\') AND
                LENGTH(SUBSTR(%s.cod,%d,LENGTH(%s.cod)-%d))=%d''' % (
                spr.tab, spr.tab, spr.id, spr.tab, parent_len, parent_code_str,
                spr.tab, parent_len + 1, spr.tab, parent_len, level_len)

        sprav = spr.tab

        #Завершить транзакцию
        _NsiList._connection.getConnection().commit()
        _NsiLevel._connection.getConnection().commit()
        #Определить форму выбора кода
        if form is None:
            form = NsiHlpFormName(typSprav, x_level)
        #Вывести окно и возвратить выбранный код
        print('SQL Query: ', sql)
        #evsp=util.InitEvalSpace({'sprav_type':typSprav, 'sprav_code':parent_code,'sprav_field':field,'parent_form':parentForm})
        evsp = icwidget.icResObjContext()
        evsp.update({
            'sprav_type': typSprav,
            'sprav_code': parent_code,
            'sprav_field': field,
            'parent_form': parentForm
        })
        res_val = ResultForm(form,
                             filter={sprav: sql},
                             evalSpace=evsp,
                             parent=parentForm,
                             bBuff=True)
        result = IC_HLP_OK
    except:
        LogLastError('HlpSprav ERROR')
        result = IC_HLP_FAILED_TYPE_SPRAV

    print('HlpSprav Result: ', result, ' HlpSprav Value: ', res_val)
    return res_val
Esempio n. 15
0
def CtrlSpravId(typSprav,
                value,
                old=None,
                flds=None,
                datatime=None,
                bCount=True,
                tab=None):
    """
    @type typSprav: C{string}
    @param typSprav: Тип справочника.
    @type cod: C{string}
    @param cod: Код справочника.
    @type value: C{...}
    @param value: Проверяемое значение идентификатора.
    @type old: C{...}
    @param old: Старое значение.
    @type field: C{string}
    @param filed: Поле, по которому проверяется значение.
    @type flds: C{dictionary}
    @param flds: Словарь соответствий между полями определенного класса данных и
        полями справочника. Если контроль значения пройдет успешно, то
        соответствующие значения из справочника будут перенесены в поля класса
        данных. Пример: {'summa':'f1', 'summa2':'f2'}
    @type datatime: C{string}
    @param datatime: Время актуальности кода.
    @type bCount: C{string}
    @param bCount: признак того, что необходимо вести количество ссылок.
    @type tab: C{string}
    @param tab: Имя класса данных справочника, если оно не указано, то функция определит
        имя класса данных справочника по таблице типов справочников.
    @rtype: C{int}
    @return: Код возврата функции контроля.
    """

    result = IC_CTRL_OK
    res_val = {}

    #   Создаем все необходимые классы данных.
    #   1. Типы справочников (getNsiListClassName())
    #   2. Класс хранения справочника (поле tab класса типов)
    #   3. Класс хранения изменяемых во времени параметров
    #       (поле tab класса типов + 'T').
    print('CtrlSprav_id, id, flds, tab=', value, flds, tab)
    try:

        if not tab:
            #   Определяем имя класса данных справочника
            #   Создаем класс данных типов справочников
            _NsiList = tabclass.CreateTabClass(getNsiListClassName())

            #   Находим описание нужного справочника
            rs = _NsiList.select(_NsiList.q.type == typSprav)
            print(rs)
            #if len(rs) == 0:
            if GetRecordCount(rs) == 0:
                print('Invalid sprav type')
                return (IC_CTRL_FAILED_TYPE_SPRAV, res_val)

            tab = rs[0].tab

        result = IC_CTRL_FAILED

        #   Если указано время актуальности, ищем в таблице изм. во времени
        #   параметров
        if datatime:
            tab = tab + 'T'

        _Sprav = tabclass.CreateTabClass(tab)
        row = _Sprav(value)

        try:
            result = IC_CTRL_OK

            #   Формируем словарь значений, которые необходимо вернуть
            if type(flds) == type({}):
                for key in flds:
                    fld_sprav = flds[key]

                    try:
                        res_val[key] = getattr(row, fld_sprav)
                    except:
                        print(
                            'Invalid attribute name "%s" in CtrlSprav class=%s, id=%s'
                            % (fld_sprav, tab, str(value)))

        except IndexError:
            result = IC_CTRL_FAILED

    except:
        LogLastError('CtrlSprav ERROR')
        result = IC_CTRL_FAILED_TYPE_SPRAV

    return (result, res_val)
Esempio n. 16
0
def CtrlSprav(typSprav,
              val,
              old=None,
              field='name',
              flds=None,
              datatime=None,
              bCount=True,
              cod=''):
    """
    @type typSprav: C{string}
    @param typSprav: Тип справочника.
    @type cod: C{string}
    @param cod: Начальная подстрока структурного кода, ограничивающая множество возможных кодов.
    @type val: C{...}
    @param val: Проверяемое значение. Если тип картеж, то это означает, что проверяем структурное
        значение (например иерархический код справочника).
    @type old: C{...}
    @param old: Старое значение.
    @type field: C{string}
    @param filed: Поле, по которому проверяется значение.
    @type flds: C{dictionary}
    @param flds: Словарь соответствий между полями определенного класса данных и
        полями справочника. Если контроль значения пройдет успешно, то
        соответствующие значения из справочника будут перенесены в поля класса
        данных. Пример: {'summa':'f1', 'summa2':'f2'}
    @type datatime: C{string}
    @param datatime: Время актуальности кода.
    @type bCount: C{string}
    @param bCount: признак того, что необходимо вести количество ссылок.
    @rtype: C{int}
    @return: Код возврата функции контроля.
    """
    result = IC_CTRL_OK
    res_val = {}

    #   Создаем все необходимые классы данных.
    #   1. Типы справочников (getNsiListClassName())
    #   2. Класс хранения справочника (поле tab класса типов)
    #   3. Класс хранения изменяемых во времени параметров
    #       (поле tab класса типов + 'T').
    try:
        #   Определяем имя класса данных справочника
        #   Создаем класс данных типов справочников
        _NsiList = tabclass.CreateTabClass(getNsiListClassName())

        #   Находим описание нужного справочника
        rs = _NsiList.select(_NsiList.q.type == typSprav)

        if GetRecordCount(rs) == 0:
            print('Invalid sprav type')
            return IC_CTRL_FAILED_TYPE_SPRAV, res_val

        spr = rs[0]

        #   Создаем классы данных справочника и изменяемых во времени параметров

        _Sprav = tabclass.CreateTabClass(spr.tab)

        cnList = _NsiList._connection.getConnection()
        cnSprav = _Sprav._connection.getConnection()
        cnSpravT = None

        result = IC_CTRL_FAILED

        # -----------------------------------------------------------------------
        if isinstance(val, tuple):
            value = ''.join([str(x) for x in val])
        else:
            value = val

        # -----------------------------------------------------------------------
        #   Если указана дата актуальности
        if datatime:
            _SpravT = tabclass.CreateTabClass(spr.tab + 'T')
            cnSpravT = _SpravT._connection.getConnection()

            rs = _SpravT.select(
                AND(_Sprav.q.id_nsi_listID == spr.id,
                    _SpravT.q.id_nsi_stdID == _Sprav.q.id,
                    _SpravT.q.time_start <= datatime,
                    _SpravT.q.time_end >= datatime,
                    getattr(_SpravT.q, field) == value,
                    _SpravT.q.cod.startswith(cod)))

        #-----------------------------------------------------------------------
        #   Если дата актуальности не указана либо в таблице актуальности нет инф.
        #   за нужный период, то проверяем по справочной таблице
        #if not datatime or len(rs) == 0:
        if not datatime or GetRecordCount(rs) == 0:
            rs = _Sprav.select(
                AND(_Sprav.q.id_nsi_listID == spr.id,
                    getattr(_Sprav.q, field) == value,
                    _Sprav.q.cod.startswith(cod)))

        try:
            row = rs[0]
            result = IC_CTRL_OK

            #   Формируем словарь значений, которые необходимо вернуть
            if type(flds) == type({}):
                for key in flds:
                    fld_sprav = flds[key]

                    try:
                        res_val[key] = getattr(row, fld_sprav)
                    except:
                        print(
                            'Invalid attribute name "%s" in CtrlSprav class=%s'
                            % (fld_sprav, spr.tab))

        except IndexError:
            result = IC_CTRL_FAILED

    except:
        print('__ except CtrlSprav:', typSprav, val, old, field, flds)
        LogLastError('CtrlSprav ERROR')
        result = IC_CTRL_FAILED_TYPE_SPRAV

    cnList.commit()
    cnSprav.commit()

    if cnSpravT:
        cnSpravT.commit()

    return (result, res_val)