Работа со справочниками

В системе используются 3 базы данных.

  1. Основание системы - SQL база, которая хранит в себе значения ячеек и их историю. Работа с базой данных происходит через интерфейс хранимых процедур, а не на прямую.

  2. Mongo - хранит в себе описание всех моделей и их взаимосвязей. На Mongo реализованы механизмы работы в режиме SandBox - когда пользовательские изменения изолируются друг от друга. В Mongo нет информации о данных из таблицы [Core].[Cells]

  3. Redis - способ кэширования данных - используется для оптимизации

Для калькулятора реализовано несколько вспомогательных классов, для получения информации из справочников. Все эти классы понаследованы от базового Base.js и расположены в папке ./classes/calculator/helpers. Классы работают с Mongo базой и кэшируют результаты своей деятельности в Redis

Функционал базового класса - получение из кэша и сохранение в кэш плюс своя функция запросов к Mongo - query, которая является оберткой над обычным запросом find, но в зависимости от контекста документа подключает или нет режим работы в песочнице.

module.exports = function(Context){

    var self = this;

    self.Context = _.clone(Context);

    self.query = function(modelName,query,fields){}

    self.cacheKey = function(){}

    self.loadFromCache = function(done){}

    self.saveToCache = function(Result,done){}
}

Документ (Doc.js)

Класс предназначен для получения следующей информации:

  1. Основные поля документа

  2. Если документ рассчитан на работу с дочерними объектами учета - мы получим информацию о возможных объектах учета для данного документа

  3. Информация о том кто этот документ подписывает

Подробнее о некоторых полях:

  • IsShowRoots - Отображать прикрепленные строки полностью или только их дочерние строки

  • IsActiveCondition - Доступна или нет панель настроек в режиме ввода

  • IsOlap IsChart IsPresent IsInput - Доступны или нет режимы OLAP, График, Презентация, Форма ввода

  • Для режима HasChildObjs = true - (документ работает на дочерних объектах учета) доступны дополнительные настройки:

  • Link_docobjtype - фильтрация дочерних объектов учета для документа

  • IsDivObj - отображать дочерние объекты отдельным выбором или склеить ряды для всех объектов учета

  • IsObjToRow - режим похожий на OLAP отчет - когда вместо рядов отображаются дочерние объекты учета

  • IsShowParentObj - дополнительная настройка для IsObjToRow - когда дочерние объекты отображаются вместе с родительскими в структуре "дерево"

{
   CodeDoc: "calc_chernmed",
   NameDoc: "Калькуляция черновой меди",
   PrintNameDoc: "Калькуляция черновой меди",
   PrintNumDoc: "",
   HasChildObjs: true,
   IsShowRoots: false,
   IsActiveCondition: false,
   IsPrimary: false,
   IsAnalytic: false,
   IsOlap: false,
   IsInput: true,
   IsChart: false,
   IsPresent: false,
   IsDivObj: true,
   IsObjToRow: false,
   IsShowParentObj: false,
   CodeModel: "TPFP",
   CodeGrp: "CALC_CU",
   CodeRole: "COST",
   CodeDocType: "MONTHDOC",
   Labels: [{
      IsSignature: true,
      IsApproval: false,
      CodePeriodGrp: "PLAN",
      CodeLabel: "gdir",
      NameLabel: "Генеральный директор",
      Idx: 1,
      Users: {
         473: {
            421: {
               NameUser: "######## ########### ###########",
               CodeUser: "421",
               JobTitle: "Генеральный директор",
               CodeOrg: "473"
            }
         }
      }
   }],
   ChildObjs: ["3272","5341","5342"]
}

Ряд (Row.js)

Получение рядов, отображаемых в таблицах. Для получения структуры берется информация из ссылок RowDoc (привязанные к документу корневые узлы) с учетом IsExpandTree (показывать только 1 строку или все дочерние узлы) При работе с OLAP документом IsExpandTree не учитывается и всегда считается false; В зависимости от параметра документа IsShowRoots корневые узлы будут отображаться или будут отображаться только их дочерние ряды

В зависимости от года передаваемого в запрос могут произойти следующие изменения: Ряд может быть исключен на основании значений полей FromObsolete и FromYear Ряд может изменить свой флажок IsFormula в зависимости от полей FormulaFromObsolete и FormulaFromYear

При тонкой фильтрации рядов используются следующие параметры: NoFiltered - строка (включая всю цепочку родительских узлов) всегда показывается HasFilteredChild - для всех дочерних строк применяется фильтрация на основании модели ObjGrp - в которой может быть установлена связь между рядом и объектом учета (или группой объектов или типом объектов)

Конструкции, когда по дереву происходит установка флага фильтрации HasFilteredChild->NoFiltered->HasFilteredChild приводят к ошибке.

Кроме этого для каждого ряда заполняется информация о его суммовых группах (если установленн флаг UseProdSumGrps, то суммовые метки применяются к списку продукции), тэгах и информация о форматировании значений.

{
   CodeRow: "m200090",
   NameRow: "Рентабельность продаж",
   IndexRow: 0,
   NumRow: "1.3.1",
   IsFormula: true,
   Formula: "$m200080? / $m200060? * 100",
   IsSum: false,
   NoSum: false,
   IsMinus: false,
   IsControlPoint: false,
   IsCalcSum: false,
   IsAgFormula: false,
   AgFormula: "",
   AsAgFormula: true,
   NoDoSum: false,
   UseProdSumGrps: false,
   CodeValuta: "NONE",
   CodeParentRow: "m200080",
   rgt: 4286,
   lft: 4285,
   level: 3,
   Sums: [ ],
   Filter: [ ],
   Tags: [
      "olap_osnpok:1",
      "numberformat:0.##",
      "AsAgFomula:1",
      "fstr:1"
   ],
   IsLeaf: true,
   Format: "0.##"
}

Для рядов подключен механизм работы с деревьями Nested Sets подробнее можно почитатьздесь

Корневые узлы (DocRow.js)

Этот класс используется только для того, чтобы по любому коду ряда можно было получить название его основного документа. Так как один и тот же ряд может быть подключен в качестве корневого ряда к нескольким документам, при этом, на данный момент, он не имеет явного признака - какой из документов главный - то решение задачи становится не очевидным.

Сейчас используется следующий алгоритм поиска документа:

  1. Предпочтение отдается документам без IsOlap IsChart IsPresent

  2. IsExpandTree у ссылки true - предпочтительней

  3. Для документов не на корневых объектах учета core.Docs.HasChildObjs=0

    1. Количество корневых узлов - выбирается документ с наименьшим числом корневых узлов в таблице link.DocRows

    2. Длина кода документа - выбирается документ с наименьшей длиной кода в поле core.Docs.CodeDoc

  4. Для документов на дочерних объектах учета core.Docs.HasChildObjs=1

    1. Определяется тип или класс объекта учета из контекста

    2. В таблице link.DocObjs фильтруется перечень документов, из которых нужный определяется по типу или классу.

    3. Если все параметры сошлись, но осталось несколько документов, то выбирается документ с более коротким кодом core.Docs.CodeDoc

При обращении к классу вы получите хэш таблицу, для вычисления кодов документов

{
    WithChildObjs: {
    z100: {
        Empty: {
            Empty: "calc_balproiz"
        },
        CALCED: {
            CE_STL: "calc_chermet",
            CE_STPK: "calc_chermet",
            CE_STKL: "calc_chermet",
            ...
            CE_ZN: "calc_zn"
        }
    },
    z112: {
        Empty: {
            Empty: "calc_ruda"
        },
        CALCEDOLD: {
            CE_SCR: "calc_ruda_pered",
    ...
    },
    NoChildObjs: {
        a111: "balans",
        r214: "finres",
        ...
        b265: "zp_zatr_conto69"
    }
}

Объект учета (Div.js)

Получение информации по объектам учета. Полная информация распределена по следующим таблицам:

Модель

Поля

obj

CodeObjType, CodeOrg, CodeParentObj

org

CodeDiv, CodeOtrasl, CodeCity

city

CodeRegion

objtype

CodeObjClass

objtag

информация о Тэгах

Обращаясь к этому классу вы получаете собранную полную информацию обо всех объектах учета плюс информацию по иерархии RootObj, CodeParentObj, Children, AllChildren :

{
    CodeObj: "473",
    IsFormula: false,
    Formula: "",
    CodeValuta: "RUB",
    CodeObjType: "OWNORG",
    CodeOrg: "473",
    CodeParentObj: "353",
    CodeDiv: "MET",
    CodeObjClass: "ORGS",
    Groups: [
        "OPR",
        "G1",
        "G5",
        "DIV_MET",
        "G2"
    ],
    CodeCity: "35379",
    CodeRegion: "56",
    CodeOtrasl: "ЦМ",
    Tags: [
        "carow:CA_STRUCT2000"
    ],
    RootObj: "353",
    Children: [
        "1873",
        "5829"    
    ],
    AllChildren: [
        "1873",
        "5829"
    ]
}

Период (Period.js)

В системе есть следующие типы периодов

  1. Обычные (расчетные) все остальные типы так или иначе приводятся к ним

19: {
      CodePeriod: "19",
      Name: "сен.",
      SName: "сен.",
      MCount: 1,
      MonthStart: 9,
      Conditions: {
         ismonth: true,
         issumperiod: false,
         iskorrperiod: false,
         isplanperiod: false,
         isozhidperiod: false
      }
}
  1. Формульные периоды (начинаются со знака "-"). Содержат хэш таблицу преобразования периода из контекста в расчетный период. Если в качестве значения используются массивы, то расчетчик суммирует входящие в массив периоды.

-201: {
   1: "1",
   2: "2",
   3: "3",
   4: "4",
   12: "22",
   13: "1",
   14: "24",
   15: "25",
  ...
   619: "629",
   6110: "6210",
   6111: "6211",
   6112: "6212"
},

Кроме информации о периодах класс отдает информацию о том, какое название периода использовать после формульных преобразований (позднее эта информация используется в получении колонок документа). Эта информация хранится в хэш таблице DisplayNames.

DisplayNames: {
   -201: {
      403: "403"
   },
   -406: {
      406: "406"
   },
   -311: {
      31: "311",
      32: "312",
      33: "313",
      34: "314"
   },
   ...

Last updated